Commit c6018fc6 authored by Dan Carpenter's avatar Dan Carpenter Committed by Daniel Borkmann

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: d90ec262 ("libbpf: Add enum64 support for btf_dump")
Signed-off-by: default avatarDan Carpenter <dan.carpenter@oracle.com>
Signed-off-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
Acked-by: default avatarMartin KaFai Lau <kafai@fb.com>
Link: https://lore.kernel.org/bpf/YtZ+LpgPADm7BeEd@kili
parent 9cb61fda
...@@ -2045,7 +2045,7 @@ static int btf_dump_get_enum_value(struct btf_dump *d, ...@@ -2045,7 +2045,7 @@ static int btf_dump_get_enum_value(struct btf_dump *d,
*value = *(__s64 *)data; *value = *(__s64 *)data;
return 0; return 0;
case 4: case 4:
*value = is_signed ? *(__s32 *)data : *(__u32 *)data; *value = is_signed ? (__s64)*(__s32 *)data : *(__u32 *)data;
return 0; return 0;
case 2: case 2:
*value = is_signed ? *(__s16 *)data : *(__u16 *)data; *value = is_signed ? *(__s16 *)data : *(__u16 *)data;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment