diff options
author | Dan Carpenter <dan.carpenter@oracle.com> | 2022-07-19 12:49:34 +0300 |
---|---|---|
committer | Daniel Borkmann <daniel@iogearbox.net> | 2022-07-21 14:24:18 +0200 |
commit | c6018fc6e7b6fcc4ac5430870c2e8b4ca556621a (patch) | |
tree | 597b404ce47c25c8bfa1250d03ca63e3128c44ce | |
parent | 9cb61fda8c71baaff423fe5be2e609100860fa78 (diff) | |
download | linux-stable-c6018fc6e7b6fcc4ac5430870c2e8b4ca556621a.tar.gz linux-stable-c6018fc6e7b6fcc4ac5430870c2e8b4ca556621a.tar.bz2 linux-stable-c6018fc6e7b6fcc4ac5430870c2e8b4ca556621a.zip |
libbpf: Fix sign expansion bug in btf_dump_get_enum_value()
The code here is supposed to take a signed int and store it in a signed
long long. Unfortunately, the way that the type promotion works with
this conditional statement is that it takes a signed int, type promotes
it to a __u32, and then stores that as a signed long long. The result is
never negative.
This is from static analysis, but I made a little test program just to
test it before I sent the patch:
#include <stdio.h>
int main(void)
{
unsigned long long src = -1ULL;
signed long long dst1, dst2;
int is_signed = 1;
dst1 = is_signed ? *(int *)&src : *(unsigned int *)0;
dst2 = is_signed ? (signed long long)*(int *)&src : *(unsigned int *)0;
printf("%lld\n", dst1);
printf("%lld\n", dst2);
return 0;
}
Fixes: d90ec262b35b ("libbpf: Add enum64 support for btf_dump")
Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: Martin KaFai Lau <kafai@fb.com>
Link: https://lore.kernel.org/bpf/YtZ+LpgPADm7BeEd@kili
-rw-r--r-- | tools/lib/bpf/btf_dump.c | 2 |
1 files changed, 1 insertions, 1 deletions
diff --git a/tools/lib/bpf/btf_dump.c b/tools/lib/bpf/btf_dump.c index 400e84fd0578..627edb5bb6de 100644 --- a/tools/lib/bpf/btf_dump.c +++ b/tools/lib/bpf/btf_dump.c @@ -2045,7 +2045,7 @@ static int btf_dump_get_enum_value(struct btf_dump *d, *value = *(__s64 *)data; return 0; case 4: - *value = is_signed ? *(__s32 *)data : *(__u32 *)data; + *value = is_signed ? (__s64)*(__s32 *)data : *(__u32 *)data; return 0; case 2: *value = is_signed ? *(__s16 *)data : *(__u16 *)data; |