From f05ddc6771c4a2eb1801dfdd0f7a212a78fa18a7 Mon Sep 17 00:00:00 2001 From: Leon Hwang Date: Mon, 18 May 2026 22:54:42 +0800 Subject: [PATCH 1/4] bpf: Check tail zero of bpf_common_attr using offsetofend Because of the 8-byte alignment, the compiler will pad struct bpf_common_attr to 24 bytes. That said, sizeof(attr_common) is 24 instead of 20. When check tail zero using sizeof(attr_common) in bpf_check_uarg_tail_zero(), there will be 4 bytes that won't be checked. To also check the padding 4 bytes, replace sizeof(attr_common) with offsetofend(struct bpf_common_attr, log_true_size). Fixes: f28771c0691b ("bpf: Extend BPF syscall with common attributes support") Signed-off-by: Leon Hwang Link: https://lore.kernel.org/r/20260518145446.6794-2-leon.hwang@linux.dev Signed-off-by: Alexei Starovoitov --- kernel/bpf/syscall.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c index 6600e126fbfb..83de8fb9b9aa 100644 --- a/kernel/bpf/syscall.c +++ b/kernel/bpf/syscall.c @@ -6278,7 +6278,9 @@ static int __sys_bpf(enum bpf_cmd cmd, bpfptr_t uattr, unsigned int size, memset(&attr_common, 0, sizeof(attr_common)); if (cmd & BPF_COMMON_ATTRS) { - err = bpf_check_uarg_tail_zero(uattr_common, sizeof(attr_common), size_common); + err = bpf_check_uarg_tail_zero(uattr_common, + offsetofend(struct bpf_common_attr, log_true_size), + size_common); if (err) return err; From b4844cb6d1ecff732c99b70998749973c6f50591 Mon Sep 17 00:00:00 2001 From: Leon Hwang Date: Mon, 18 May 2026 22:54:44 +0800 Subject: [PATCH 2/4] libbpf: Add OPTS_VALID() for log_opts in bpf_map_create There should be an OPTS_VALID() check for log_opts before extracting its fields. If no such OPTS_VALID() check and an application compiled against a future libbpf header passes a log_opts with new, non-zero fields to libbpf.so, those fields will be ignored silently. Fixes: 702259006f93 ("libbpf: Add syscall common attributes support for map_create") Signed-off-by: Leon Hwang Link: https://lore.kernel.org/r/20260518145446.6794-4-leon.hwang@linux.dev Signed-off-by: Alexei Starovoitov --- tools/lib/bpf/bpf.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tools/lib/bpf/bpf.c b/tools/lib/bpf/bpf.c index 483c02cf21d1..3cd705802330 100644 --- a/tools/lib/bpf/bpf.c +++ b/tools/lib/bpf/bpf.c @@ -246,6 +246,9 @@ int bpf_map_create(enum bpf_map_type map_type, attr.excl_prog_hash_size = OPTS_GET(opts, excl_prog_hash_size, 0); log_opts = OPTS_GET(opts, log_opts, NULL); + if (!OPTS_VALID(log_opts, bpf_log_opts)) + return libbpf_err(-EINVAL); + if (log_opts && feat_supported(NULL, FEAT_BPF_SYSCALL_COMMON_ATTRS)) { memset(&attr_common, 0, attr_common_sz); attr_common.log_buf = ptr_to_u64(OPTS_GET(log_opts, buf, NULL)); From 652f0c2c999d28d820bbe2e1aa16d8e0fea369ea Mon Sep 17 00:00:00 2001 From: Leon Hwang Date: Mon, 18 May 2026 22:54:45 +0800 Subject: [PATCH 3/4] selftests/bpf: Use -1 as token_fd in map create failure test Because 0xFF can be an open BPF token fd in the test runner that will fail test_invalid_token_fd(), change token_fd from 0xFF to -1 to avoid such test failure. Fixes: f675483cac1d ("selftests/bpf: Add tests to verify map create failure log") Signed-off-by: Leon Hwang Link: https://lore.kernel.org/r/20260518145446.6794-5-leon.hwang@linux.dev Signed-off-by: Alexei Starovoitov --- tools/testing/selftests/bpf/prog_tests/map_init.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/testing/selftests/bpf/prog_tests/map_init.c b/tools/testing/selftests/bpf/prog_tests/map_init.c index 5c61c8e37306..b0b902d5783d 100644 --- a/tools/testing/selftests/bpf/prog_tests/map_init.c +++ b/tools/testing/selftests/bpf/prog_tests/map_init.c @@ -306,7 +306,7 @@ static void test_invalid_token_fd(void) const char *msg = "Invalid map_token_fd.\n"; LIBBPF_OPTS(bpf_map_create_opts, opts, .map_flags = BPF_F_TOKEN_FD, - .token_fd = 0xFF, + .token_fd = -1, ); test_map_create_array(&opts, msg); From 7732ad2412fd402913976e490921f7e792a0a33b Mon Sep 17 00:00:00 2001 From: Leon Hwang Date: Mon, 18 May 2026 22:54:46 +0800 Subject: [PATCH 4/4] selftests/bpf: Add test to verify checking padding bytes for BPF syscall common attributes Add a test to verify that the tailing padding 4 bytes are checked in syscall.c::__sys_bpf() using bpf_check_uarg_tail_zero(). Without the fix, the test fails with: test_common_attr_padding:FAIL:syscall unexpected syscall: actual 4 >= expected 0 #213/12 map_create_failure/common_attr_padding:FAIL Signed-off-by: Leon Hwang Link: https://lore.kernel.org/r/20260518145446.6794-6-leon.hwang@linux.dev Signed-off-by: Alexei Starovoitov --- .../selftests/bpf/prog_tests/map_init.c | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/tools/testing/selftests/bpf/prog_tests/map_init.c b/tools/testing/selftests/bpf/prog_tests/map_init.c index b0b902d5783d..c804c3ce9be9 100644 --- a/tools/testing/selftests/bpf/prog_tests/map_init.c +++ b/tools/testing/selftests/bpf/prog_tests/map_init.c @@ -353,6 +353,30 @@ static void test_excl_prog_hash_size_2(void) test_map_create_array(&opts, msg); } +static void test_common_attr_padding(void) +{ + struct bpf_common_attr_fake { + __u8 attrs[offsetofend(struct bpf_common_attr, log_true_size)]; + __u32 pad; + } attr_common = { + .pad = 1, + }; + union bpf_attr attr = { + .map_type = BPF_MAP_TYPE_ARRAY, + .key_size = 4, + .value_size = 4, + .max_entries = 1, + }; + int fd; + + fd = syscall(__NR_bpf, BPF_MAP_CREATE | BPF_COMMON_ATTRS, &attr, sizeof(attr), &attr_common, + sizeof(attr_common)); + if (!ASSERT_LT(fd, 0, "syscall")) + close(fd); + else + ASSERT_EQ(errno, E2BIG, "errno"); +} + void test_map_create_failure(void) { if (test__start_subtest("invalid_vmlinux_value_type_id_struct_ops")) @@ -377,4 +401,6 @@ void test_map_create_failure(void) test_excl_prog_hash_size_1(); if (test__start_subtest("invalid_excl_prog_hash_size_2")) test_excl_prog_hash_size_2(); + if (test__start_subtest("common_attr_padding")) + test_common_attr_padding(); }