* [PATCH bpf-next v2 0/3] bpf: Check tail zero of bpf_map_info and bpf_prog_info
@ 2026-06-04 15:05 Leon Hwang
2026-06-04 15:05 ` [PATCH bpf-next v2 1/3] bpf: Check tail zero of bpf_map_info Leon Hwang
` (2 more replies)
0 siblings, 3 replies; 7+ messages in thread
From: Leon Hwang @ 2026-06-04 15:05 UTC (permalink / raw)
To: bpf
Cc: Alexei Starovoitov, Daniel Borkmann, John Fastabend,
Andrii Nakryiko, Martin KaFai Lau, Eduard Zingerman,
Kumar Kartikeya Dwivedi, Song Liu, Yonghong Song, Jiri Olsa,
Shuah Khan, Yuyang Huang, Leon Hwang, KP Singh, Dave Marchevsky,
Stanislav Fomichev, linux-kernel, linux-kselftest,
kernel-patches-bot
Check the tail bytes of bpf_map_info and bpf_prog_info due to padding
when getting map info and prog info via BPF_OBJ_GET_INFO_BY_FD, which
was discussed in the thread
"bpf: Check tail zero of bpf_common_attr using offsetofend" [1].
Links:
[1] https://lore.kernel.org/bpf/20260518145446.6794-2-leon.hwang@linux.dev/
Changes:
v1 -> v2:
* Collect Acked-by tags from Mykyta, thanks.
* Update Fixes tag in patch #2 (per bot+bpf-ci)
* v1: https://lore.kernel.org/bpf/20260603144518.67065-1-leon.hwang@linux.dev/
Leon Hwang (3):
bpf: Check tail zero of bpf_map_info
bpf: Check tail zero of bpf_prog_info
selftests/bpf: Add tests to verify checking padding bytes for
bpf_[map,prog]_info
kernel/bpf/syscall.c | 10 ++--
.../selftests/bpf/prog_tests/bpf_attr_size.c | 55 +++++++++++++++++++
2 files changed, 61 insertions(+), 4 deletions(-)
--
2.54.0
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH bpf-next v2 1/3] bpf: Check tail zero of bpf_map_info
2026-06-04 15:05 [PATCH bpf-next v2 0/3] bpf: Check tail zero of bpf_map_info and bpf_prog_info Leon Hwang
@ 2026-06-04 15:05 ` Leon Hwang
2026-06-04 15:45 ` bot+bpf-ci
2026-06-04 15:05 ` [PATCH bpf-next v2 2/3] bpf: Check tail zero of bpf_prog_info Leon Hwang
2026-06-04 15:05 ` [PATCH bpf-next v2 3/3] selftests/bpf: Add tests to verify checking padding bytes for bpf_[map,prog]_info Leon Hwang
2 siblings, 1 reply; 7+ messages in thread
From: Leon Hwang @ 2026-06-04 15:05 UTC (permalink / raw)
To: bpf
Cc: Alexei Starovoitov, Daniel Borkmann, John Fastabend,
Andrii Nakryiko, Martin KaFai Lau, Eduard Zingerman,
Kumar Kartikeya Dwivedi, Song Liu, Yonghong Song, Jiri Olsa,
Shuah Khan, Yuyang Huang, Leon Hwang, KP Singh, Dave Marchevsky,
Stanislav Fomichev, linux-kernel, linux-kselftest,
kernel-patches-bot, Mykyta Yatsenko
Since there're 4 bytes padding at the end of struct bpf_map_info, they
won't be checked by bpf_check_uarg_tail_zero().
pahole -C bpf_map_info ./vmlinux
struct bpf_map_info {
...
__u64 hash __attribute__((__aligned__(8))); /* 88 8 */
__u32 hash_size; /* 96 4 */
/* size: 104, cachelines: 2, members: 18 */
/* padding: 4 */
/* forced alignments: 1 */
/* last cacheline: 40 bytes */
} __attribute__((__aligned__(8)));
If a future kernel extension adds a new 4-byte field, older userspace
programs allocating this structure on the stack might inadvertently pass
uninitialized stack garbage into the new field, permanently breaking
backward compatibility. -- sashiko [1]
Fix it by changing sizeof(info) to
offsetofend(struct bpf_map_info, hash_size).
[1] https://lore.kernel.org/bpf/20260513224823.6494FC19425@smtp.kernel.org/
Fixes: ea2e6467ac36 ("bpf: Return hashes of maps in BPF_OBJ_GET_INFO_BY_FD")
Acked-by: Mykyta Yatsenko <yatsenko@meta.com>
Signed-off-by: Leon Hwang <leon.hwang@linux.dev>
---
kernel/bpf/syscall.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index 625a4366fe6d..1007fb7c87e9 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -5400,10 +5400,11 @@ static int bpf_map_get_info_by_fd(struct file *file,
{
struct bpf_map_info __user *uinfo = u64_to_user_ptr(attr->info.info);
struct bpf_map_info info;
- u32 info_len = attr->info.info_len;
+ u32 info_len = attr->info.info_len, len;
int err;
- err = bpf_check_uarg_tail_zero(USER_BPFPTR(uinfo), sizeof(info), info_len);
+ len = offsetofend(struct bpf_map_info, hash_size);
+ err = bpf_check_uarg_tail_zero(USER_BPFPTR(uinfo), len, info_len);
if (err)
return err;
info_len = min_t(u32, sizeof(info), info_len);
--
2.54.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH bpf-next v2 2/3] bpf: Check tail zero of bpf_prog_info
2026-06-04 15:05 [PATCH bpf-next v2 0/3] bpf: Check tail zero of bpf_map_info and bpf_prog_info Leon Hwang
2026-06-04 15:05 ` [PATCH bpf-next v2 1/3] bpf: Check tail zero of bpf_map_info Leon Hwang
@ 2026-06-04 15:05 ` Leon Hwang
2026-06-04 15:45 ` bot+bpf-ci
2026-06-04 15:05 ` [PATCH bpf-next v2 3/3] selftests/bpf: Add tests to verify checking padding bytes for bpf_[map,prog]_info Leon Hwang
2 siblings, 1 reply; 7+ messages in thread
From: Leon Hwang @ 2026-06-04 15:05 UTC (permalink / raw)
To: bpf
Cc: Alexei Starovoitov, Daniel Borkmann, John Fastabend,
Andrii Nakryiko, Martin KaFai Lau, Eduard Zingerman,
Kumar Kartikeya Dwivedi, Song Liu, Yonghong Song, Jiri Olsa,
Shuah Khan, Yuyang Huang, Leon Hwang, KP Singh, Dave Marchevsky,
Stanislav Fomichev, linux-kernel, linux-kselftest,
kernel-patches-bot, Mykyta Yatsenko
Since there're 4 bytes padding at the end of struct bpf_prog_info, they
won't be checked by bpf_check_uarg_tail_zero().
pahole -C bpf_prog_info ./vmlinux
struct bpf_prog_info {
...
__u32 attach_btf_obj_id; /* 220 4 */
__u32 attach_btf_id; /* 224 4 */
/* size: 232, cachelines: 4, members: 38 */
/* sum members: 224 */
/* sum bitfield members: 1 bits, bit holes: 1, sum bit holes: 31 bits */
/* padding: 4 */
/* forced alignments: 9 */
/* last cacheline: 40 bytes */
} __attribute__((__aligned__(8)));
If a future kernel extension adds a new 4-byte field, older userspace
programs allocating this structure on the stack might inadvertently pass
uninitialized stack garbage into the new field, permanently breaking
backward compatibility. -- sashiko [1]
Fix it by changing sizeof(info) to
offsetofend(struct bpf_prog_info, attach_btf_id).
[1] https://lore.kernel.org/bpf/20260513224823.6494FC19425@smtp.kernel.org/
Fixes: aba64c7da983 ("bpf: Add verified_insns to bpf_prog_info and fdinfo")
Acked-by: Mykyta Yatsenko <yatsenko@meta.com>
Signed-off-by: Leon Hwang <leon.hwang@linux.dev>
---
kernel/bpf/syscall.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index 1007fb7c87e9..0c86a70d31c1 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -5115,10 +5115,11 @@ static int bpf_prog_get_info_by_fd(struct file *file,
u32 info_len = attr->info.info_len;
struct bpf_prog_kstats stats;
char __user *uinsns;
- u32 ulen;
+ u32 ulen, len;
int err;
- err = bpf_check_uarg_tail_zero(USER_BPFPTR(uinfo), sizeof(info), info_len);
+ len = offsetofend(struct bpf_prog_info, attach_btf_id);
+ err = bpf_check_uarg_tail_zero(USER_BPFPTR(uinfo), len, info_len);
if (err)
return err;
info_len = min_t(u32, sizeof(info), info_len);
--
2.54.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH bpf-next v2 3/3] selftests/bpf: Add tests to verify checking padding bytes for bpf_[map,prog]_info
2026-06-04 15:05 [PATCH bpf-next v2 0/3] bpf: Check tail zero of bpf_map_info and bpf_prog_info Leon Hwang
2026-06-04 15:05 ` [PATCH bpf-next v2 1/3] bpf: Check tail zero of bpf_map_info Leon Hwang
2026-06-04 15:05 ` [PATCH bpf-next v2 2/3] bpf: Check tail zero of bpf_prog_info Leon Hwang
@ 2026-06-04 15:05 ` Leon Hwang
2 siblings, 0 replies; 7+ messages in thread
From: Leon Hwang @ 2026-06-04 15:05 UTC (permalink / raw)
To: bpf
Cc: Alexei Starovoitov, Daniel Borkmann, John Fastabend,
Andrii Nakryiko, Martin KaFai Lau, Eduard Zingerman,
Kumar Kartikeya Dwivedi, Song Liu, Yonghong Song, Jiri Olsa,
Shuah Khan, Yuyang Huang, Leon Hwang, KP Singh, Dave Marchevsky,
Stanislav Fomichev, linux-kernel, linux-kselftest,
kernel-patches-bot
Add two tests to verify that the tail padding 4 bytes of struct
bpf_map_info and bpf_prog_info are checked in syscall.c using
bpf_check_uarg_tail_zero().
Signed-off-by: Leon Hwang <leon.hwang@linux.dev>
---
.../selftests/bpf/prog_tests/bpf_attr_size.c | 55 +++++++++++++++++++
1 file changed, 55 insertions(+)
diff --git a/tools/testing/selftests/bpf/prog_tests/bpf_attr_size.c b/tools/testing/selftests/bpf/prog_tests/bpf_attr_size.c
index 32159dc64da8..87842c4347a6 100644
--- a/tools/testing/selftests/bpf/prog_tests/bpf_attr_size.c
+++ b/tools/testing/selftests/bpf/prog_tests/bpf_attr_size.c
@@ -62,8 +62,63 @@ static void test_query_size_boundaries(void)
cgroup_skb_direct_packet_access__destroy(skel);
}
+static void test_map_info_tail_zero(void)
+{
+ LIBBPF_OPTS(bpf_map_create_opts, map_opts);
+ struct bpf_map_info_fake {
+ __u8 info[offsetofend(struct bpf_map_info, hash_size)];
+ __u32 pad;
+ } info = {
+ .pad = 1,
+ };
+ int map_fd, err;
+ __u32 info_len;
+
+ map_fd = bpf_map_create(BPF_MAP_TYPE_ARRAY, "arr", sizeof(int), 1, 1, &map_opts);
+ if (!ASSERT_GE(map_fd, 0, "bpf_map_create"))
+ return;
+
+ info_len = sizeof(info);
+ err = bpf_obj_get_info_by_fd(map_fd, &info, &info_len);
+ ASSERT_EQ(err, -E2BIG, "bpf_obj_get_info_by_fd");
+
+ close(map_fd);
+}
+
+static void test_prog_info_tail_zero(void)
+{
+ LIBBPF_OPTS(bpf_prog_load_opts, prog_opts);
+ struct bpf_insn insns[] = {
+ BPF_MOV64_IMM(BPF_REG_0, 0),
+ BPF_EXIT_INSN(),
+ };
+ struct bpf_prog_info_fake {
+ __u8 info[offsetofend(struct bpf_prog_info, attach_btf_id)];
+ __u32 pad;
+ } info = {
+ .pad = 1,
+ };
+ int prog_fd, err;
+ __u32 info_len;
+
+ prog_fd = bpf_prog_load(BPF_PROG_TYPE_SOCKET_FILTER, "test_prog", "GPL", insns,
+ ARRAY_SIZE(insns), &prog_opts);
+ if (!ASSERT_GE(prog_fd, 0, "bpf_prog_load"))
+ return;
+
+ info_len = sizeof(info);
+ err = bpf_obj_get_info_by_fd(prog_fd, &info, &info_len);
+ ASSERT_EQ(err, -E2BIG, "bpf_obj_get_info_by_fd");
+
+ close(prog_fd);
+}
+
void test_bpf_attr_size(void)
{
if (test__start_subtest("query_size_boundaries"))
test_query_size_boundaries();
+ if (test__start_subtest("map_info_tail_zero"))
+ test_map_info_tail_zero();
+ if (test__start_subtest("prog_info_tail_zero"))
+ test_prog_info_tail_zero();
}
--
2.54.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH bpf-next v2 2/3] bpf: Check tail zero of bpf_prog_info
2026-06-04 15:05 ` [PATCH bpf-next v2 2/3] bpf: Check tail zero of bpf_prog_info Leon Hwang
@ 2026-06-04 15:45 ` bot+bpf-ci
0 siblings, 0 replies; 7+ messages in thread
From: bot+bpf-ci @ 2026-06-04 15:45 UTC (permalink / raw)
To: leon.hwang, bpf
Cc: ast, daniel, john.fastabend, andrii, martin.lau, eddyz87, memxor,
song, yonghong.song, jolsa, shuah, yuyanghuang, leon.hwang,
kpsingh, davemarchevsky, sdf, linux-kernel, linux-kselftest,
kernel-patches-bot, yatsenko, ast, andrii, daniel, martin.lau,
eddyz87, yonghong.song, clm, ihor.solodrai
[-- Attachment #1: Type: text/plain, Size: 2094 bytes --]
> diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
> index 1007fb7c87e9..0c86a70d31c1 100644
> --- a/kernel/bpf/syscall.c
> +++ b/kernel/bpf/syscall.c
> @@ -5115,10 +5115,11 @@ static int bpf_prog_get_info_by_fd(struct file *file,
> u32 info_len = attr->info.info_len;
> struct bpf_prog_kstats stats;
> char __user *uinsns;
> - u32 ulen;
> + u32 ulen, len;
> int err;
>
> - err = bpf_check_uarg_tail_zero(USER_BPFPTR(uinfo), sizeof(info), info_len);
> + len = offsetofend(struct bpf_prog_info, attach_btf_id);
> + err = bpf_check_uarg_tail_zero(USER_BPFPTR(uinfo), len, info_len);
A concern raised during the v1 review on the list does not appear to
have been resolved in the code, so it seems worth raising again here.
With len now equal to 228 instead of sizeof(info) == 232, a caller that
passes info_len == 232 will have actual_size (232) greater than
expected_size (228), so bpf_check_uarg_tail_zero() will actively check
the 4 padding bytes and return -E2BIG when they contain garbage.
Could this reject callers that work today? An existing binary that
allocates struct bpf_prog_info on the stack and passes info_len == 232
without zeroing the trailing padding would have hit the fast path
(actual_size <= expected_size) before this change and returned 0.
There was also a question about whether this actually prevents the
future-field scenario described in the commit message. If a later
kernel adds a new 4-byte field, the struct size stays 232 and that
kernel's expected_size becomes 232, so an old binary passing
info_len == 232 hits the fast path again and the uninitialized padding
is consumed as the new field.
For reference, the original discussion is here:
https://lore.kernel.org/bpf/20260603151405.6DB111F00893@smtp.kernel.org/
> if (err)
> return err;
> info_len = min_t(u32, sizeof(info), info_len);
---
AI reviewed your patch. Please fix the bug or email reply why it's not a bug.
See: https://github.com/kernel-patches/vmtest/blob/master/ci/claude/README.md
CI run summary: https://github.com/kernel-patches/bpf/actions/runs/26960942650
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH bpf-next v2 1/3] bpf: Check tail zero of bpf_map_info
2026-06-04 15:05 ` [PATCH bpf-next v2 1/3] bpf: Check tail zero of bpf_map_info Leon Hwang
@ 2026-06-04 15:45 ` bot+bpf-ci
2026-06-04 16:39 ` Alexei Starovoitov
0 siblings, 1 reply; 7+ messages in thread
From: bot+bpf-ci @ 2026-06-04 15:45 UTC (permalink / raw)
To: leon.hwang, bpf
Cc: ast, daniel, john.fastabend, andrii, martin.lau, eddyz87, memxor,
song, yonghong.song, jolsa, shuah, yuyanghuang, leon.hwang,
kpsingh, davemarchevsky, sdf, linux-kernel, linux-kselftest,
kernel-patches-bot, yatsenko, ast, andrii, daniel, martin.lau,
eddyz87, yonghong.song, clm, ihor.solodrai
[-- Attachment #1: Type: text/plain, Size: 2096 bytes --]
> diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
> index 625a4366fe6d..1007fb7c87e9 100644
> --- a/kernel/bpf/syscall.c
> +++ b/kernel/bpf/syscall.c
> @@ -5400,10 +5400,11 @@ static int bpf_map_get_info_by_fd(struct file *file,
> {
> struct bpf_map_info __user *uinfo = u64_to_user_ptr(attr->info.info);
> struct bpf_map_info info;
> - u32 info_len = attr->info.info_len;
> + u32 info_len = attr->info.info_len, len;
> int err;
>
> - err = bpf_check_uarg_tail_zero(USER_BPFPTR(uinfo), sizeof(info), info_len);
> + len = offsetofend(struct bpf_map_info, hash_size);
> + err = bpf_check_uarg_tail_zero(USER_BPFPTR(uinfo), len, info_len);
Does this change break the ABI for existing deployed binaries? Previously,
expected_size was 104 (sizeof(info)). If an existing binary passes info_len
= 104 with uninitialized stack garbage in the 4-byte padding,
bpf_check_uarg_tail_zero() would see actual_size <= expected_size (104 <=
104) and immediately return 0.
By reducing expected_size to 100, actual_size > expected_size (104 > 100),
so bpf_check_uarg_tail_zero() will actively check the 4 padding bytes and
return -E2BIG if they contain garbage. This rejects previously working
applications.
Additionally, does this actually protect against the stated future issue?
If a future kernel adds a new 4-byte field, the struct size stays 104, and
the new kernel's expected_size will be 104. At that point, those old buggy
binaries passing info_len = 104 will once again hit the fast path
(actual_size <= expected_size), skipping the check and allowing the
uninitialized padding to be consumed as the new field.
Reference: https://lore.kernel.org/bpf/20260603151405.6DB111F00893@smtp.kernel.org/
From: sashiko-bot@kernel.org
Date: Wed, 03 Jun 2026 15:14:05 +0000
> if (err)
> return err;
> info_len = min_t(u32, sizeof(info), info_len);
---
AI reviewed your patch. Please fix the bug or email reply why it's not a bug.
See: https://github.com/kernel-patches/vmtest/blob/master/ci/claude/README.md
CI run summary: https://github.com/kernel-patches/bpf/actions/runs/26960942650
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH bpf-next v2 1/3] bpf: Check tail zero of bpf_map_info
2026-06-04 15:45 ` bot+bpf-ci
@ 2026-06-04 16:39 ` Alexei Starovoitov
0 siblings, 0 replies; 7+ messages in thread
From: Alexei Starovoitov @ 2026-06-04 16:39 UTC (permalink / raw)
To: bot+bpf-ci
Cc: Leon Hwang, bpf, Alexei Starovoitov, Daniel Borkmann,
John Fastabend, Andrii Nakryiko, Martin KaFai Lau, Eduard,
Kumar Kartikeya Dwivedi, Song Liu, Yonghong Song, Jiri Olsa,
Shuah Khan, Yuyang Huang, KP Singh, Dave Marchevsky,
Stanislav Fomichev, LKML, open list:KERNEL SELFTEST FRAMEWORK,
kernel-patches-bot, Mykyta Yatsenko, Martin KaFai Lau,
Chris Mason, Ihor Solodrai
On Thu, Jun 4, 2026 at 8:45 AM <bot+bpf-ci@kernel.org> wrote:
>
> > diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
> > index 625a4366fe6d..1007fb7c87e9 100644
> > --- a/kernel/bpf/syscall.c
> > +++ b/kernel/bpf/syscall.c
> > @@ -5400,10 +5400,11 @@ static int bpf_map_get_info_by_fd(struct file *file,
> > {
> > struct bpf_map_info __user *uinfo = u64_to_user_ptr(attr->info.info);
> > struct bpf_map_info info;
> > - u32 info_len = attr->info.info_len;
> > + u32 info_len = attr->info.info_len, len;
> > int err;
> >
> > - err = bpf_check_uarg_tail_zero(USER_BPFPTR(uinfo), sizeof(info), info_len);
> > + len = offsetofend(struct bpf_map_info, hash_size);
> > + err = bpf_check_uarg_tail_zero(USER_BPFPTR(uinfo), len, info_len);
>
> Does this change break the ABI for existing deployed binaries? Previously,
> expected_size was 104 (sizeof(info)). If an existing binary passes info_len
> = 104 with uninitialized stack garbage in the 4-byte padding,
> bpf_check_uarg_tail_zero() would see actual_size <= expected_size (104 <=
> 104) and immediately return 0.
>
> By reducing expected_size to 100, actual_size > expected_size (104 > 100),
> so bpf_check_uarg_tail_zero() will actively check the 4 padding bytes and
> return -E2BIG if they contain garbage. This rejects previously working
> applications.
>
> Additionally, does this actually protect against the stated future issue?
> If a future kernel adds a new 4-byte field, the struct size stays 104, and
> the new kernel's expected_size will be 104. At that point, those old buggy
> binaries passing info_len = 104 will once again hit the fast path
> (actual_size <= expected_size), skipping the check and allowing the
> uninitialized padding to be consumed as the new field.
bot's concerns are valid.
Let's add __u32 :32 to bpf_map_info at the same time.
pw-bot: cr
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2026-06-04 16:39 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-04 15:05 [PATCH bpf-next v2 0/3] bpf: Check tail zero of bpf_map_info and bpf_prog_info Leon Hwang
2026-06-04 15:05 ` [PATCH bpf-next v2 1/3] bpf: Check tail zero of bpf_map_info Leon Hwang
2026-06-04 15:45 ` bot+bpf-ci
2026-06-04 16:39 ` Alexei Starovoitov
2026-06-04 15:05 ` [PATCH bpf-next v2 2/3] bpf: Check tail zero of bpf_prog_info Leon Hwang
2026-06-04 15:45 ` bot+bpf-ci
2026-06-04 15:05 ` [PATCH bpf-next v2 3/3] selftests/bpf: Add tests to verify checking padding bytes for bpf_[map,prog]_info Leon Hwang
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox