As reported in [0] and [1], kernel and userspace can sometimes disagree on the definition of a typedef (in particular, the size). This leads to trouble when userspace maps the memory of a bpf program and reads/writes to it assuming a different memory layout. This commit now uses the libbpf sized ints logic when emitting the skeleton. This resolves int types to int32_t-like equivalents and ensures that typedefs are not just emitted verbatim. The drive-by selftest changes fix format specifier issues due to the definitions of [us]64 and (u)int64_t differing in how many longs they use (long long int vs long int on x86_64). [0]: https://github.com/iovisor/bcc/pull/3777 [1]: Closes: https://github.com/libbpf/libbpf/issues/433 Signed-off-by: Delyan Kratunov <delyank@xxxxxx> --- tools/bpf/bpftool/gen.c | 3 +++ .../testing/selftests/bpf/prog_tests/skeleton.c | 16 ++++++++-------- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/tools/bpf/bpftool/gen.c b/tools/bpf/bpftool/gen.c index eacfc6a2060d..18c3f755ad88 100644 --- a/tools/bpf/bpftool/gen.c +++ b/tools/bpf/bpftool/gen.c @@ -146,6 +146,7 @@ static int codegen_datasec_def(struct bpf_object *obj, .field_name = var_ident, .indent_level = 2, .strip_mods = strip_mods, + .sizedints = true, ); int need_off = sec_var->offset, align_off, align; __u32 var_type_id = var->type; @@ -751,6 +752,7 @@ static int do_skeleton(int argc, char **argv) #ifndef %2$s \n\ #define %2$s \n\ \n\ + #include <inttypes.h> \n\ #include <stdlib.h> \n\ #include <bpf/bpf.h> \n\ #include <bpf/skel_internal.h> \n\ @@ -770,6 +772,7 @@ static int do_skeleton(int argc, char **argv) #define %2$s \n\ \n\ #include <errno.h> \n\ + #include <inttypes.h> \n\ #include <stdlib.h> \n\ #include <bpf/libbpf.h> \n\ \n\ diff --git a/tools/testing/selftests/bpf/prog_tests/skeleton.c b/tools/testing/selftests/bpf/prog_tests/skeleton.c index 180afd632f4c..9894e1b39211 100644 --- a/tools/testing/selftests/bpf/prog_tests/skeleton.c +++ b/tools/testing/selftests/bpf/prog_tests/skeleton.c @@ -43,13 +43,13 @@ void test_skeleton(void) /* validate values are pre-initialized correctly */ CHECK(data->in1 != -1, "in1", "got %d != exp %d\n", data->in1, -1); CHECK(data->out1 != -1, "out1", "got %d != exp %d\n", data->out1, -1); - CHECK(data->in2 != -1, "in2", "got %lld != exp %lld\n", data->in2, -1LL); - CHECK(data->out2 != -1, "out2", "got %lld != exp %lld\n", data->out2, -1LL); + CHECK(data->in2 != -1, "in2", "got %"PRId64" != exp %lld\n", data->in2, -1LL); + CHECK(data->out2 != -1, "out2", "got %"PRId64" != exp %lld\n", data->out2, -1LL); CHECK(bss->in3 != 0, "in3", "got %d != exp %d\n", bss->in3, 0); CHECK(bss->out3 != 0, "out3", "got %d != exp %d\n", bss->out3, 0); - CHECK(bss->in4 != 0, "in4", "got %lld != exp %lld\n", bss->in4, 0LL); - CHECK(bss->out4 != 0, "out4", "got %lld != exp %lld\n", bss->out4, 0LL); + CHECK(bss->in4 != 0, "in4", "got %"PRId64" != exp %lld\n", bss->in4, 0LL); + CHECK(bss->out4 != 0, "out4", "got %"PRId64" != exp %lld\n", bss->out4, 0LL); CHECK(rodata->in.in6 != 0, "in6", "got %d != exp %d\n", rodata->in.in6, 0); CHECK(bss->out6 != 0, "out6", "got %d != exp %d\n", bss->out6, 0); @@ -77,9 +77,9 @@ void test_skeleton(void) /* validate pre-setup values are still there */ CHECK(data->in1 != 10, "in1", "got %d != exp %d\n", data->in1, 10); - CHECK(data->in2 != 11, "in2", "got %lld != exp %lld\n", data->in2, 11LL); + CHECK(data->in2 != 11, "in2", "got %"PRId64" != exp %lld\n", data->in2, 11LL); CHECK(bss->in3 != 12, "in3", "got %d != exp %d\n", bss->in3, 12); - CHECK(bss->in4 != 13, "in4", "got %lld != exp %lld\n", bss->in4, 13LL); + CHECK(bss->in4 != 13, "in4", "got %"PRId64" != exp %lld\n", bss->in4, 13LL); CHECK(rodata->in.in6 != 14, "in6", "got %d != exp %d\n", rodata->in.in6, 14); ASSERT_EQ(rodata_dyn->in_dynarr_sz, 4, "in_dynarr_sz"); @@ -105,9 +105,9 @@ void test_skeleton(void) usleep(1); CHECK(data->out1 != 1, "res1", "got %d != exp %d\n", data->out1, 1); - CHECK(data->out2 != 2, "res2", "got %lld != exp %d\n", data->out2, 2); + CHECK(data->out2 != 2, "res2", "got %"PRId64" != exp %d\n", data->out2, 2); CHECK(bss->out3 != 3, "res3", "got %d != exp %d\n", (int)bss->out3, 3); - CHECK(bss->out4 != 4, "res4", "got %lld != exp %d\n", bss->out4, 4); + CHECK(bss->out4 != 4, "res4", "got %"PRId64" != exp %d\n", bss->out4, 4); CHECK(bss->out5.a != 5, "res5", "got %d != exp %d\n", bss->out5.a, 5); CHECK(bss->out5.b != 6, "res6", "got %lld != exp %d\n", bss->out5.b, 6); CHECK(bss->out6 != 14, "res7", "got %d != exp %d\n", bss->out6, 14); -- 2.34.1