kernel/bpf/helpers.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
The user constructed a BPF program containing a bpf_snprintf() call.
The fmt parameter passed to bpf_snprintf() was not assigned a value;
it only executed the BPF_MAP_FREEZE command to freeze the fmt string.
Furthermore, when bpf_check() executed check_reg_const_str() and
check_bpf_snprintf_call() to check the fmt input parameter of the
user-constructed BPF program's bpf_snprintf() call, strnchr() only
checked if fmt was a null-terminated string. This led the BPF verifier
to incorrectly assume the constant format string was valid.
When the BPF program was actually executed, the out-of-bounds (OOB)
issue reported by syzbot occurred [1].
This issue is strongly related to bpf_snprintf(), therefore adding a
check for an empty format string in check_bpf_snprintf_call() would
be beneficial. Since it calls bpf_bprintf_prepare(), only adding a
check on the result of strnchr() is needed to prevent the case where
the format string is empty.
[1]
BUG: KASAN: slab-out-of-bounds in strnchr+0x5e/0x80 lib/string.c:405
Read of size 1 at addr ffff888029e093b0 by task ksoftirqd/1/23
Call Trace:
strnchr+0x5e/0x80 lib/string.c:405
bpf_bprintf_prepare+0x167/0x13d0 kernel/bpf/helpers.c:829
____bpf_snprintf kernel/bpf/helpers.c:1065 [inline]
bpf_snprintf+0xd3/0x1b0 kernel/bpf/helpers.c:1049
Allocated by task 6022:
__bpf_map_area_alloc kernel/bpf/syscall.c:395 [inline]
bpf_map_area_alloc+0x64/0x180 kernel/bpf/syscall.c:408
insn_array_alloc+0x52/0x140 kernel/bpf/bpf_insn_array.c:49
map_create+0xafd/0x16a0 kernel/bpf/syscall.c:1514
The buggy address is located 0 bytes to the right of
allocated 944-byte region [ffff888029e09000, ffff888029e093b0)
Fixes: d9c9e4db186a ("bpf: Factorize bpf_trace_printk and bpf_seq_printf")
Reported-by: syzbot+2c29addf92581b410079@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=2c29addf92581b410079
Tested-by: syzbot+2c29addf92581b410079@syzkaller.appspotmail.com
Signed-off-by: Edward Adam Davis <eadavis@qq.com>
---
kernel/bpf/helpers.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c
index db72b96f9c8c..88da2d0e634c 100644
--- a/kernel/bpf/helpers.c
+++ b/kernel/bpf/helpers.c
@@ -827,7 +827,7 @@ int bpf_bprintf_prepare(const char *fmt, u32 fmt_size, const u64 *raw_args,
char fmt_ptype, cur_ip[16], ip_spec[] = "%pXX";
fmt_end = strnchr(fmt, fmt_size, 0);
- if (!fmt_end)
+ if (!fmt_end || fmt_end == fmt)
return -EINVAL;
fmt_size = fmt_end - fmt;
--
2.43.0
On Wed, Jan 7, 2026 at 1:39 AM Edward Adam Davis <eadavis@qq.com> wrote:
>
> The user constructed a BPF program containing a bpf_snprintf() call.
> The fmt parameter passed to bpf_snprintf() was not assigned a value;
> it only executed the BPF_MAP_FREEZE command to freeze the fmt string.
> Furthermore, when bpf_check() executed check_reg_const_str() and
> check_bpf_snprintf_call() to check the fmt input parameter of the
> user-constructed BPF program's bpf_snprintf() call, strnchr() only
> checked if fmt was a null-terminated string. This led the BPF verifier
> to incorrectly assume the constant format string was valid.
> When the BPF program was actually executed, the out-of-bounds (OOB)
> issue reported by syzbot occurred [1].
>
> This issue is strongly related to bpf_snprintf(), therefore adding a
> check for an empty format string in check_bpf_snprintf_call() would
> be beneficial. Since it calls bpf_bprintf_prepare(), only adding a
> check on the result of strnchr() is needed to prevent the case where
> the format string is empty.
>
> [1]
> BUG: KASAN: slab-out-of-bounds in strnchr+0x5e/0x80 lib/string.c:405
> Read of size 1 at addr ffff888029e093b0 by task ksoftirqd/1/23
> Call Trace:
> strnchr+0x5e/0x80 lib/string.c:405
> bpf_bprintf_prepare+0x167/0x13d0 kernel/bpf/helpers.c:829
> ____bpf_snprintf kernel/bpf/helpers.c:1065 [inline]
> bpf_snprintf+0xd3/0x1b0 kernel/bpf/helpers.c:1049
>
> Allocated by task 6022:
> __bpf_map_area_alloc kernel/bpf/syscall.c:395 [inline]
> bpf_map_area_alloc+0x64/0x180 kernel/bpf/syscall.c:408
> insn_array_alloc+0x52/0x140 kernel/bpf/bpf_insn_array.c:49
> map_create+0xafd/0x16a0 kernel/bpf/syscall.c:1514
>
> The buggy address is located 0 bytes to the right of
> allocated 944-byte region [ffff888029e09000, ffff888029e093b0)
>
> Fixes: d9c9e4db186a ("bpf: Factorize bpf_trace_printk and bpf_seq_printf")
> Reported-by: syzbot+2c29addf92581b410079@syzkaller.appspotmail.com
> Closes: https://syzkaller.appspot.com/bug?extid=2c29addf92581b410079
> Tested-by: syzbot+2c29addf92581b410079@syzkaller.appspotmail.com
> Signed-off-by: Edward Adam Davis <eadavis@qq.com>
> ---
> kernel/bpf/helpers.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c
> index db72b96f9c8c..88da2d0e634c 100644
> --- a/kernel/bpf/helpers.c
> +++ b/kernel/bpf/helpers.c
> @@ -827,7 +827,7 @@ int bpf_bprintf_prepare(const char *fmt, u32 fmt_size, const u64 *raw_args,
> char fmt_ptype, cur_ip[16], ip_spec[] = "%pXX";
>
> fmt_end = strnchr(fmt, fmt_size, 0);
> - if (!fmt_end)
> + if (!fmt_end || fmt_end == fmt)
> return -EINVAL;
I don't think you root caused it correctly.
The better fix and analysis:
https://patchwork.kernel.org/project/netdevbpf/patch/20260107021037.289644-1-kartikey406@gmail.com/
pw-bot: cr
On Wed, 7 Jan 2026 19:02:37 -0800, Alexei Starovoitov <alexei.starovoitov@gmail.com> wrote:
> > diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c
> > index db72b96f9c8c..88da2d0e634c 100644
> > --- a/kernel/bpf/helpers.c
> > +++ b/kernel/bpf/helpers.c
> > @@ -827,7 +827,7 @@ int bpf_bprintf_prepare(const char *fmt, u32 fmt_size, const u64 *raw_args,
> > char fmt_ptype, cur_ip[16], ip_spec[] = "%pXX";
> >
> > fmt_end = strnchr(fmt, fmt_size, 0);
> > - if (!fmt_end)
> > + if (!fmt_end || fmt_end == fmt)
> > return -EINVAL;
>
> I don't think you root caused it correctly.
> The better fix and analysis:
I am keeping my analysis and patch.
The root cause of the problem is that the format string does not contain
a null terminator ('\0').
Filtering out map type 0x22 to solve the problem is too hasty, as it
would prevent all instructions from calling functions with constant
string arguments.
On Wed, Jan 7, 2026 at 7:52 PM Edward Adam Davis <eadavis@qq.com> wrote:
>
> On Wed, 7 Jan 2026 19:02:37 -0800, Alexei Starovoitov <alexei.starovoitov@gmail.com> wrote:
> > > diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c
> > > index db72b96f9c8c..88da2d0e634c 100644
> > > --- a/kernel/bpf/helpers.c
> > > +++ b/kernel/bpf/helpers.c
> > > @@ -827,7 +827,7 @@ int bpf_bprintf_prepare(const char *fmt, u32 fmt_size, const u64 *raw_args,
> > > char fmt_ptype, cur_ip[16], ip_spec[] = "%pXX";
> > >
> > > fmt_end = strnchr(fmt, fmt_size, 0);
> > > - if (!fmt_end)
> > > + if (!fmt_end || fmt_end == fmt)
> > > return -EINVAL;
> >
> > I don't think you root caused it correctly.
> > The better fix and analysis:
> I am keeping my analysis and patch.
> The root cause of the problem is that the format string does not contain
> a null terminator ('\0').
> Filtering out map type 0x22 to solve the problem is too hasty, as it
> would prevent all instructions from calling functions with constant
> string arguments.
If you think it's still possible to construct a program that
passes empty const string into this helper then please craft
a selftest that demonstrates that.
© 2016 - 2026 Red Hat, Inc.