[syzbot] [bpf?] general protection fault in print_reg_state

11 views
Skip to first unread message

syzbot

unread,
Sep 23, 2025, 5:02:33 AM (8 days ago) Sep 23
to and...@kernel.org, a...@kernel.org, b...@vger.kernel.org, dan...@iogearbox.net, edd...@gmail.com, hao...@google.com, john.fa...@gmail.com, jo...@kernel.org, kps...@kernel.org, linux-...@vger.kernel.org, marti...@linux.dev, s...@fomichev.me, so...@kernel.org, syzkall...@googlegroups.com, yongho...@linux.dev
Hello,

syzbot found the following issue on:

HEAD commit: cec1e6e5d1ab Merge tag 'sched_ext-for-6.17-rc7-fixes' of g..
git tree: upstream
console output: https://syzkaller.appspot.com/x/log.txt?x=175418e2580000
kernel config: https://syzkaller.appspot.com/x/.config?x=8f01d8629880e620
dashboard link: https://syzkaller.appspot.com/bug?extid=d36d5ae81e1b0a53ef58
compiler: gcc (Debian 12.2.0-14+deb12u1) 12.2.0, GNU ld (GNU Binutils for Debian) 2.40
syz repro: https://syzkaller.appspot.com/x/repro.syz?x=113bf8e2580000
C reproducer: https://syzkaller.appspot.com/x/repro.c?x=1608c27c580000

Downloadable assets:
disk image (non-bootable): https://storage.googleapis.com/syzbot-assets/d900f083ada3/non_bootable_disk-cec1e6e5.raw.xz
vmlinux: https://storage.googleapis.com/syzbot-assets/2833a04dba30/vmlinux-cec1e6e5.xz
kernel image: https://storage.googleapis.com/syzbot-assets/632491f232df/bzImage-cec1e6e5.xz

IMPORTANT: if you fix the issue, please add the following tag to the commit:
Reported-by: syzbot+d36d5a...@syzkaller.appspotmail.com

Oops: general protection fault, probably for non-canonical address 0xdffffc000000000c: 0000 [#1] SMP KASAN NOPTI
KASAN: null-ptr-deref in range [0x0000000000000060-0x0000000000000067]
CPU: 1 UID: 0 PID: 6117 Comm: syz.0.17 Not tainted syzkaller #0 PREEMPT(full)
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2~bpo12+1 04/01/2014
RIP: 0010:print_reg_state+0x2dc/0x1010 kernel/bpf/log.c:719
Code: c1 ea 03 80 3c 02 00 0f 85 5c 0c 00 00 48 ba 00 00 00 00 00 fc ff df 4c 8b 7b 08 49 8d 47 60 48 89 c1 48 89 04 24 48 c1 e9 03 <0f> b6 14 11 84 d2 74 06 0f 8e 45 0b 00 00 41 0f b6 57 60 48 8b 44
RSP: 0018:ffffc90004e67398 EFLAGS: 00010206
RAX: 0000000000000060 RBX: ffff8880275a5000 RCX: 000000000000000c
RDX: dffffc0000000000 RSI: ffffffff81daeb8b RDI: 0000000000000005
RBP: ffffc90004e674b0 R08: 0000000000000005 R09: 0000000000000002
R10: 0000000000000000 R11: 0000000000000000 R12: ffff888037df0000
R13: 0000000000000003 R14: 1ffff920009cce79 R15: 0000000000000000
FS: 0000555587b13500(0000) GS:ffff8880d67b2000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 0000200000000100 CR3: 0000000033bb5000 CR4: 0000000000352ef0
Call Trace:
<TASK>
print_verifier_state+0x234/0x1170 kernel/bpf/log.c:775
do_check kernel/bpf/verifier.c:20071 [inline]
do_check_common+0x283e/0xb410 kernel/bpf/verifier.c:23264
do_check_main kernel/bpf/verifier.c:23347 [inline]
bpf_check+0x869f/0xc670 kernel/bpf/verifier.c:24707
bpf_prog_load+0xe41/0x2490 kernel/bpf/syscall.c:2979
__sys_bpf+0x4a3f/0x4de0 kernel/bpf/syscall.c:6029
__do_sys_bpf kernel/bpf/syscall.c:6139 [inline]
__se_sys_bpf kernel/bpf/syscall.c:6137 [inline]
__x64_sys_bpf+0x78/0xc0 kernel/bpf/syscall.c:6137
do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
do_syscall_64+0xcd/0x4e0 arch/x86/entry/syscall_64.c:94
entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7f1041d8eec9
Code: ff ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 40 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 a8 ff ff ff f7 d8 64 89 01 48
RSP: 002b:00007ffd44cefdd8 EFLAGS: 00000246 ORIG_RAX: 0000000000000141
RAX: ffffffffffffffda RBX: 00007f1041fe5fa0 RCX: 00007f1041d8eec9
RDX: 0000000000000094 RSI: 0000200000000100 RDI: 0000000000000005
RBP: 00007f1041e11f91 R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000
R13: 00007f1041fe5fa0 R14: 00007f1041fe5fa0 R15: 0000000000000003
</TASK>
Modules linked in:
---[ end trace 0000000000000000 ]---
RIP: 0010:print_reg_state+0x2dc/0x1010 kernel/bpf/log.c:719
Code: c1 ea 03 80 3c 02 00 0f 85 5c 0c 00 00 48 ba 00 00 00 00 00 fc ff df 4c 8b 7b 08 49 8d 47 60 48 89 c1 48 89 04 24 48 c1 e9 03 <0f> b6 14 11 84 d2 74 06 0f 8e 45 0b 00 00 41 0f b6 57 60 48 8b 44
RSP: 0018:ffffc90004e67398 EFLAGS: 00010206
RAX: 0000000000000060 RBX: ffff8880275a5000 RCX: 000000000000000c
RDX: dffffc0000000000 RSI: ffffffff81daeb8b RDI: 0000000000000005
RBP: ffffc90004e674b0 R08: 0000000000000005 R09: 0000000000000002
R10: 0000000000000000 R11: 0000000000000000 R12: ffff888037df0000
R13: 0000000000000003 R14: 1ffff920009cce79 R15: 0000000000000000
FS: 0000555587b13500(0000) GS:ffff8880d67b2000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 0000200000000100 CR3: 0000000033bb5000 CR4: 0000000000352ef0
----------------
Code disassembly (best guess):
0: c1 ea 03 shr $0x3,%edx
3: 80 3c 02 00 cmpb $0x0,(%rdx,%rax,1)
7: 0f 85 5c 0c 00 00 jne 0xc69
d: 48 ba 00 00 00 00 00 movabs $0xdffffc0000000000,%rdx
14: fc ff df
17: 4c 8b 7b 08 mov 0x8(%rbx),%r15
1b: 49 8d 47 60 lea 0x60(%r15),%rax
1f: 48 89 c1 mov %rax,%rcx
22: 48 89 04 24 mov %rax,(%rsp)
26: 48 c1 e9 03 shr $0x3,%rcx
* 2a: 0f b6 14 11 movzbl (%rcx,%rdx,1),%edx <-- trapping instruction
2e: 84 d2 test %dl,%dl
30: 74 06 je 0x38
32: 0f 8e 45 0b 00 00 jle 0xb7d
38: 41 0f b6 57 60 movzbl 0x60(%r15),%edx
3d: 48 rex.W
3e: 8b .byte 0x8b
3f: 44 rex.R


---
This report is generated by a bot. It may contain errors.
See https://goo.gl/tpsmEJ for more information about syzbot.
syzbot engineers can be reached at syzk...@googlegroups.com.

syzbot will keep track of this issue. See:
https://goo.gl/tpsmEJ#status for how to communicate with syzbot.

If the report is already addressed, let syzbot know by replying with:
#syz fix: exact-commit-title

If you want syzbot to run the reproducer, reply with:
#syz test: git://repo/address.git branch-or-commit-hash
If you attach or paste a git patch, syzbot will apply it before testing.

If you want to overwrite report's subsystems, reply with:
#syz set subsystems: new-subsystem
(See the list of subsystem names on the web dashboard)

If the report is a duplicate of another one, reply with:
#syz dup: exact-subject-of-another-report

If you want to undo deduplication, reply with:
#syz undup

Brahmajit Das

unread,
Sep 23, 2025, 12:42:24 PM (8 days ago) Sep 23
to syzbot+d36d5a...@syzkaller.appspotmail.com, lis...@listout.xyz, and...@kernel.org, a...@kernel.org, b...@vger.kernel.org, dan...@iogearbox.net, edd...@gmail.com, hao...@google.com, john.fa...@gmail.com, jo...@kernel.org, kps...@kernel.org, linux-...@vger.kernel.org, marti...@linux.dev, s...@fomichev.me, so...@kernel.org, syzkall...@googlegroups.com, yongho...@linux.dev
Syzkaller reported a general protection fault due to a NULL pointer
dereference in print_reg_state() when accessing reg->map_ptr without
checking if it is NULL.

The existing code assumes reg->map_ptr is always valid before
dereferencing reg->map_ptr->name, reg->map_ptr->key_size, and
reg->map_ptr->value_size.

Fix this by adding explicit NULL checks before accessing reg->map_ptr
and its members. This prevents crashes when reg->map_ptr is NULL,
improving the robustness of the BPF verifier's verbose logging.

Reported-by: syzbot+d36d5a...@syzkaller.appspotmail.com
Signed-off-by: Brahmajit Das <lis...@listout.xyz>
---
kernel/bpf/log.c | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/kernel/bpf/log.c b/kernel/bpf/log.c
index 38050f4ee400..a2368b21486a 100644
--- a/kernel/bpf/log.c
+++ b/kernel/bpf/log.c
@@ -3,6 +3,7 @@
* Copyright (c) 2016 Facebook
* Copyright (c) 2018 Covalent IO, Inc. http://covalent.io
*/
+#include "linux/printk.h"
#include <uapi/linux/btf.h>
#include <linux/kernel.h>
#include <linux/types.h>
@@ -716,11 +717,12 @@ static void print_reg_state(struct bpf_verifier_env *env,
if (type_is_non_owning_ref(reg->type))
verbose_a("%s", "non_own_ref");
if (type_is_map_ptr(t)) {
- if (reg->map_ptr->name[0])
+ if (reg->map_ptr != NULL && reg->map_ptr->name[0] != '\0')
verbose_a("map=%s", reg->map_ptr->name);
- verbose_a("ks=%d,vs=%d",
- reg->map_ptr->key_size,
- reg->map_ptr->value_size);
+ if (reg->map_ptr != NULL)
+ verbose_a("ks=%d,vs=%d",
+ reg->map_ptr->key_size,
+ reg->map_ptr->value_size);
}
if (t != SCALAR_VALUE && reg->off) {
verbose_a("off=");
--
2.51.0

Brahmajit Das

unread,
Sep 23, 2025, 12:44:18 PM (8 days ago) Sep 23
to syzbot+d36d5a...@syzkaller.appspotmail.com, lis...@listout.xyz, and...@kernel.org, a...@kernel.org, b...@vger.kernel.org, dan...@iogearbox.net, edd...@gmail.com, hao...@google.com, john.fa...@gmail.com, jo...@kernel.org, kps...@kernel.org, linux-...@vger.kernel.org, marti...@linux.dev, s...@fomichev.me, so...@kernel.org, syzkall...@googlegroups.com, yongho...@linux.dev
Syzkaller reported a general protection fault due to a NULL pointer
dereference in print_reg_state() when accessing reg->map_ptr without
checking if it is NULL.

The existing code assumes reg->map_ptr is always valid before
dereferencing reg->map_ptr->name, reg->map_ptr->key_size, and
reg->map_ptr->value_size.

Fix this by adding explicit NULL checks before accessing reg->map_ptr
and its members. This prevents crashes when reg->map_ptr is NULL,
improving the robustness of the BPF verifier's verbose logging.

Reported-by: syzbot+d36d5a...@syzkaller.appspotmail.com
Signed-off-by: Brahmajit Das <lis...@listout.xyz>
---
kernel/bpf/log.c | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/kernel/bpf/log.c b/kernel/bpf/log.c
index 38050f4ee400..b38efbbf22cf 100644
--- a/kernel/bpf/log.c
+++ b/kernel/bpf/log.c
@@ -716,11 +716,12 @@ static void print_reg_state(struct bpf_verifier_env *env,

Brahmajit Das

unread,
Sep 23, 2025, 1:10:28 PM (8 days ago) Sep 23
to syzbot+d36d5a...@syzkaller.appspotmail.com, lis...@listout.xyz, syzkall...@googlegroups.com
#syz test

Syzkaller reported a general protection fault due to a NULL pointer
dereference in print_reg_state() when accessing reg->map_ptr without
checking if it is NULL.

The existing code assumes reg->map_ptr is always valid before
dereferencing reg->map_ptr->name, reg->map_ptr->key_size, and
reg->map_ptr->value_size.

Fix this by adding explicit NULL checks before accessing reg->map_ptr
and its members. This prevents crashes when reg->map_ptr is NULL,
improving the robustness of the BPF verifier's verbose logging.

Reported-by: syzbot+d36d5a...@syzkaller.appspotmail.com
Signed-off-by: Brahmajit Das <lis...@listout.xyz>
---
kernel/bpf/log.c | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/kernel/bpf/log.c b/kernel/bpf/log.c
index 38050f4ee400..14c0a442a85b 100644
--- a/kernel/bpf/log.c
+++ b/kernel/bpf/log.c
@@ -715,11 +715,10 @@ static void print_reg_state(struct bpf_verifier_env *env,
verbose_a("ref_obj_id=%d", reg->ref_obj_id);
if (type_is_non_owning_ref(reg->type))
verbose_a("%s", "non_own_ref");
- if (type_is_map_ptr(t)) {
+ if (type_is_map_ptr(t) && reg->map_ptr) {
if (reg->map_ptr->name[0])
verbose_a("map=%s", reg->map_ptr->name);
- verbose_a("ks=%d,vs=%d",
- reg->map_ptr->key_size,
+ verbose_a("ks=%d,vs=%d", reg->map_ptr->key_size,
reg->map_ptr->value_size);
}
if (t != SCALAR_VALUE && reg->off) {
--
2.51.0

syzbot

unread,
Sep 23, 2025, 1:30:07 PM (8 days ago) Sep 23
to linux-...@vger.kernel.org, lis...@listout.xyz, syzkall...@googlegroups.com
Hello,

syzbot has tested the proposed patch and the reproducer did not trigger any issue:

Reported-by: syzbot+d36d5a...@syzkaller.appspotmail.com
Tested-by: syzbot+d36d5a...@syzkaller.appspotmail.com

Tested on:

commit: cec1e6e5 Merge tag 'sched_ext-for-6.17-rc7-fixes' of g..
git tree: upstream
console output: https://syzkaller.appspot.com/x/log.txt?x=14ed0f12580000
kernel config: https://syzkaller.appspot.com/x/.config?x=8f01d8629880e620
dashboard link: https://syzkaller.appspot.com/bug?extid=d36d5ae81e1b0a53ef58
compiler: gcc (Debian 12.2.0-14+deb12u1) 12.2.0, GNU ld (GNU Binutils for Debian) 2.40
patch: https://syzkaller.appspot.com/x/patch.diff?x=1647627c580000

Note: testing is done by a robot and is best-effort only.

Brahmajit Das

unread,
Sep 23, 2025, 1:48:00 PM (8 days ago) Sep 23
to syzbot+d36d5a...@syzkaller.appspotmail.com, and...@kernel.org, a...@kernel.org, b...@vger.kernel.org, dan...@iogearbox.net, edd...@gmail.com, hao...@google.com, john.fa...@gmail.com, jo...@kernel.org, kps...@kernel.org, linux-...@vger.kernel.org, marti...@linux.dev, s...@fomichev.me, so...@kernel.org, syzkall...@googlegroups.com, yongho...@linux.dev
Syzkaller reported a general protection fault due to a NULL pointer
dereference in print_reg_state() when accessing reg->map_ptr without
checking if it is NULL.

The existing code assumes reg->map_ptr is always valid before
dereferencing reg->map_ptr->name, reg->map_ptr->key_size, and
reg->map_ptr->value_size.

Fix this by adding explicit NULL checks before accessing reg->map_ptr
and its members. This prevents crashes when reg->map_ptr is NULL,
improving the robustness of the BPF verifier's verbose logging.

Reported-by: syzbot+d36d5a...@syzkaller.appspotmail.com
Signed-off-by: Brahmajit Das <lis...@listout.xyz>
---
kernel/bpf/log.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/kernel/bpf/log.c b/kernel/bpf/log.c
index f50533169cc3..5ffb8d778b92 100644
--- a/kernel/bpf/log.c
+++ b/kernel/bpf/log.c
@@ -704,7 +704,7 @@ static void print_reg_state(struct bpf_verifier_env *env,
verbose_a("ref_obj_id=%d", reg->ref_obj_id);
if (type_is_non_owning_ref(reg->type))
verbose_a("%s", "non_own_ref");
- if (type_is_map_ptr(t)) {
+ if (type_is_map_ptr(t) && reg->map_ptr) {
if (reg->map_ptr->name[0])
verbose_a("map=%s", reg->map_ptr->name);
verbose_a("ks=%d,vs=%d",
--
2.51.0

Alexei Starovoitov

unread,
Sep 23, 2025, 2:52:42 PM (7 days ago) Sep 23
to Brahmajit Das, syzbot+d36d5a...@syzkaller.appspotmail.com, Andrii Nakryiko, Alexei Starovoitov, bpf, Daniel Borkmann, Eduard, Hao Luo, John Fastabend, Jiri Olsa, KP Singh, LKML, Martin KaFai Lau, Stanislav Fomichev, Song Liu, syzkaller-bugs, Yonghong Song
Looks like you're bandaiding a symptome instead of fixing
underlying issue. For map types map_ptr should always be set.

pw-bot: cr

Alexei Starovoitov

unread,
Sep 24, 2025, 3:32:41 AM (7 days ago) Sep 24
to Brahmajit Das, syzbot+d36d5a...@syzkaller.appspotmail.com, Andrii Nakryiko, Alexei Starovoitov, bpf, Daniel Borkmann, Eduard, Hao Luo, John Fastabend, Jiri Olsa, KP Singh, LKML, Martin KaFai Lau, Stanislav Fomichev, Song Liu, syzkaller-bugs, Yonghong Song
You ignored earlier feedback.
Fix the root cause, not the symptom.

pw-bot: cr

Brahmajit Das

unread,
Sep 24, 2025, 5:09:49 AM (7 days ago) Sep 24
to Alexei Starovoitov, syzbot+d36d5a...@syzkaller.appspotmail.com, Andrii Nakryiko, Alexei Starovoitov, bpf, Daniel Borkmann, Eduard, Hao Luo, John Fastabend, Jiri Olsa, KP Singh, LKML, Martin KaFai Lau, Stanislav Fomichev, Song Liu, syzkaller-bugs, Yonghong Song
Alexei, I did not, the patches (v1 and v2) were sent in a very short
timeframe, when you gave me the feedback I had already sent the v2 so
your feedback applies to v2 as well :)

I'm working on fixing/understanding the issue. I went one function lower
from where print_reg_state is being called and added a few debugging
statements like this

--- a/kernel/bpf/log.c
+++ b/kernel/bpf/log.c
@@ -758,6 +758,12 @@ void print_verifier_state(struct bpf_verifier_env *env, const struct bpf_verifie
continue;
if (!print_all && !reg_scratched(env, i))
continue;
+ pr_err("&state->regs[%d] = %p\n", i, (void *)&state->regs[i]);
+ pr_err("reg = %p\n", (void *)reg);
+ pr_err("&reg->map_ptr = %p\n", (void *)&reg->map_ptr);
+ pr_err("&state->regs[%d].map_ptr = %p\n", i, (void *)&state->regs[i].map_ptr);
+ pr_err("state->regs[%d].map_ptr is NULL %d\n", i, state->regs[i].map_ptr == NULL);
+ pr_err("regs->map_ptr is NULL %d\n", reg->map_ptr == NULL);
verbose(env, " R%d", i);
verbose(env, "=");
print_reg_state(env, state, reg);

Both reg->map_ptr and state->regs[i].map_ptr reports map_ptr is NULL.
For now I'm bit stuck and trying to understand why that would be.
I got the reproducer from
https://syzkaller.appspot.com/text?tag=ReproC&x=1608c27c580000

--
Regards,
listout

Brahmajit Das

unread,
Sep 24, 2025, 11:41:17 AM (7 days ago) Sep 24
to Alexei Starovoitov, syzbot+d36d5a...@syzkaller.appspotmail.com, Andrii Nakryiko, Alexei Starovoitov, bpf, Daniel Borkmann, Eduard, Hao Luo, John Fastabend, Jiri Olsa, KP Singh, LKML, Martin KaFai Lau, Stanislav Fomichev, Song Liu, syzkaller-bugs, Yonghong Song
On 24.09.2025 09:32, Alexei Starovoitov wrote:
> On Wed, Sep 24, 2025 at 1:43 AM Brahmajit Das <lis...@listout.xyz> wrote:
> >
> > Syzkaller reported a general protection fault due to a NULL pointer
> > dereference in print_reg_state() when accessing reg->map_ptr without
> > checking if it is NULL.
> >
...snip...
> > - if (type_is_map_ptr(t)) {
> > + if (type_is_map_ptr(t) && reg->map_ptr) {
>
> You ignored earlier feedback.
> Fix the root cause, not the symptom.
>
> pw-bot: cr

I'm not sure if I'm headed the write direction but it seems like in
check_alu_op, we are calling adjust_scalar_min_max_vals when we get an
BPF_NEG as opcode. Which has a call to __mark_reg_known when opcode is
BPF_NEG. And __mark_reg_known clears map_ptr with

/* Clear off and union(map_ptr, range) */
memset(((u8 *)reg) + sizeof(reg->type), 0,
offsetof(struct bpf_reg_state, var_off) - sizeof(reg->type));

--
Regards,
listout

Alexei Starovoitov

unread,
Sep 24, 2025, 1:28:33 PM (7 days ago) Sep 24
to Brahmajit Das, syzbot+d36d5a...@syzkaller.appspotmail.com, Andrii Nakryiko, Alexei Starovoitov, bpf, Daniel Borkmann, Eduard, Hao Luo, John Fastabend, Jiri Olsa, KP Singh, LKML, Martin KaFai Lau, Stanislav Fomichev, Song Liu, syzkaller-bugs, Yonghong Song
On Wed, Sep 24, 2025 at 4:41 PM Brahmajit Das <lis...@listout.xyz> wrote:
>
> On 24.09.2025 09:32, Alexei Starovoitov wrote:
> > On Wed, Sep 24, 2025 at 1:43 AM Brahmajit Das <lis...@listout.xyz> wrote:
> > >
> > > Syzkaller reported a general protection fault due to a NULL pointer
> > > dereference in print_reg_state() when accessing reg->map_ptr without
> > > checking if it is NULL.
> > >
> ...snip...
> > > - if (type_is_map_ptr(t)) {
> > > + if (type_is_map_ptr(t) && reg->map_ptr) {
> >
> > You ignored earlier feedback.
> > Fix the root cause, not the symptom.
> >
> > pw-bot: cr
>
> I'm not sure if I'm headed the write direction but it seems like in
> check_alu_op, we are calling adjust_scalar_min_max_vals when we get an
> BPF_NEG as opcode. Which has a call to __mark_reg_known when opcode is
> BPF_NEG. And __mark_reg_known clears map_ptr with

Looks like we're getting somewhere.
It seems the verifier is not clearing reg->type.
adjust_scalar_min_max_vals() should be called on scalar types only.

Brahmajit Das

unread,
Sep 24, 2025, 2:28:23 PM (6 days ago) Sep 24
to KaFai Wan, Alexei Starovoitov, syzbot+d36d5a...@syzkaller.appspotmail.com, Andrii Nakryiko, Alexei Starovoitov, bpf, Daniel Borkmann, Eduard, Hao Luo, John Fastabend, Jiri Olsa, KP Singh, LKML, Martin KaFai Lau, Stanislav Fomichev, Song Liu, syzkaller-bugs, Yonghong Song
On 25.09.2025 01:38, KaFai Wan wrote:
> I think you are right. The following code can reproduce the error.
>
> asm volatile (" \
> r0 = %[map_hash_48b] ll; \
> r0 = -r0; \
> exit; \
> " :
> : __imm_addr(map_hash_48b)
> : __clobber_all);
>
>
> BPF_NEG calls __mark_reg_known(dst_reg, 0) which clears the 'off' and
> 'union(map_ptr, range)' of dst_reg, but keeps the 'type', which is
> CONST_PTR_TO_MAP.
>
> Perhaps we can only allow the SCALAR_VALUE type to run BPF_NEG as an
> opcode, while for other types same as the before BPF_NEG.
>
> diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
> index e892df386eed..dbf9f1efc6e7 100644
> --- a/kernel/bpf/verifier.c
> +++ b/kernel/bpf/verifier.c
> @@ -15346,13 +15346,15 @@ static bool
> is_safe_to_compute_dst_reg_range(struct bpf_insn *insn,
> switch (BPF_OP(insn->code)) {
> case BPF_ADD:
> case BPF_SUB:
> - case BPF_NEG:
> case BPF_AND:
> case BPF_XOR:
> case BPF_OR:
> case BPF_MUL:
> return true;
>
> + case BPF_NEG:
> + return base_type(src_reg->type) == SCALAR_VALUE;
> +
>
>
> --
> Thanks,
> KaFai

Before even going into adjust_scalar_min_max_vals we have a check in
check_alu_op, which I think is not being respected. Going to expand on
this below as response to Alexei.

On 24.09.2025 18:28, Alexei Starovoitov wrote:
> On Wed, Sep 24, 2025 at 4:41 PM Brahmajit Das <lis...@listout.xyz> wrote:
> >
> > On 24.09.2025 09:32, Alexei Starovoitov wrote:
> > > On Wed, Sep 24, 2025 at 1:43 AM Brahmajit Das <lis...@listout.xyz> wrote:
> > > >
> > > > Syzkaller reported a general protection fault due to a NULL pointer
> > > > dereference in print_reg_state() when accessing reg->map_ptr without
> > > > checking if it is NULL.
> > > >
> > ...snip...
> > > > - if (type_is_map_ptr(t)) {
> > > > + if (type_is_map_ptr(t) && reg->map_ptr) {
> > >
> > > You ignored earlier feedback.
> > > Fix the root cause, not the symptom.
> > >
> > > pw-bot: cr
> >
> > I'm not sure if I'm headed the write direction but it seems like in
> > check_alu_op, we are calling adjust_scalar_min_max_vals when we get an
> > BPF_NEG as opcode. Which has a call to __mark_reg_known when opcode is
> > BPF_NEG. And __mark_reg_known clears map_ptr with
>
> Looks like we're getting somewhere.
> It seems the verifier is not clearing reg->type.
> adjust_scalar_min_max_vals() should be called on scalar types only.

Right, there is a check in check_alu_op

if (is_pointer_value(env, insn->dst_reg)) {
verbose(env, "R%d pointer arithmetic prohibited\n",
insn->dst_reg);
return -EACCES;
}

is_pointer_value calls __is_pointer_value which takes bool
allow_ptr_leaks as the first argument. Now for some reason in this case
allow_ptr_leaks is being passed as true, as a result __is_pointer_value
(and in turn is_pointer_value) returns false when even when register
type is CONST_PTR_TO_MAP.

--
Regards,
listout

KaFai Wan

unread,
Sep 24, 2025, 3:07:54 PM (6 days ago) Sep 24
to Brahmajit Das, Alexei Starovoitov, syzbot+d36d5a...@syzkaller.appspotmail.com, Andrii Nakryiko, Alexei Starovoitov, bpf, Daniel Borkmann, Eduard, Hao Luo, John Fastabend, Jiri Olsa, KP Singh, LKML, Martin KaFai Lau, Stanislav Fomichev, Song Liu, syzkaller-bugs, Yonghong Song
On Wed, 2025-09-24 at 21:10 +0530, Brahmajit Das wrote:

KaFai Wan

unread,
Sep 25, 2025, 11:32:10 AM (6 days ago) Sep 25
to Brahmajit Das, Alexei Starovoitov, syzbot+d36d5a...@syzkaller.appspotmail.com, Andrii Nakryiko, Alexei Starovoitov, bpf, Daniel Borkmann, Eduard, Hao Luo, John Fastabend, Jiri Olsa, KP Singh, LKML, Martin KaFai Lau, Stanislav Fomichev, Song Liu, syzkaller-bugs, Yonghong Song
IIUC, `env->allow_ptr_leaks` set true means privileged mode (
CAP_PERFMON or CAP_SYS_ADMIN ), false for unprivileged mode.


We can use __is_pointer_value to check if the register type is a
pointer. For pointers, we check as before (before checking BPF_NEG
separately), and for scalars, it remains unchanged. Perhaps this way we
can fix the error.

if (opcode == BPF_NEG) {
if (__is_pointer_value(false, &regs[insn->dst_reg])) {
err = check_reg_arg(env, insn->dst_reg, DST_OP);
} else {
err = check_reg_arg(env, insn->dst_reg,
DST_OP_NO_MARK);
err = err ?: adjust_scalar_min_max_vals(env, insn,
&regs[insn->dst_reg],
regs[insn->dst_reg]);
}
} else {


--
Thanks,
KaFai

Brahmajit Das

unread,
Sep 25, 2025, 9:04:31 PM (5 days ago) Sep 25
to KaFai Wan, Alexei Starovoitov, syzbot+d36d5a...@syzkaller.appspotmail.com, Andrii Nakryiko, Alexei Starovoitov, bpf, Daniel Borkmann, Eduard, Hao Luo, John Fastabend, Jiri Olsa, KP Singh, LKML, Martin KaFai Lau, Stanislav Fomichev, Song Liu, syzkaller-bugs, Yonghong Song
On 25.09.2025 23:31, KaFai Wan wrote:
> On Wed, 2025-09-24 at 23:58 +0530, Brahmajit Das wrote:
> > On 25.09.2025 01:38, KaFai Wan wrote:
> > > On Wed, 2025-09-24 at 21:10 +0530, Brahmajit Das wrote:
> > > > On 24.09.2025 09:32, Alexei Starovoitov wrote:
> > > > > On Wed, Sep 24, 2025 at 1:43 AM Brahmajit Das
> > > > > <lis...@listout.xyz>
> > > > > wrote:
> > > > > >
> > > > > > Syzkaller reported a general protection fault due to a NULL
> > > > > > pointer
> > > > > > dereference in print_reg_state() when accessing reg->map_ptr
> > > > > > without
> > > > > > checking if it is NULL.
> > > > > >
...snip...
> > >
Yep, that works.

--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -15505,10 +15505,17 @@ static int check_alu_op(struct bpf_verifier_env *env, struct bpf_insn *insn)

/* check dest operand */
if (opcode == BPF_NEG) {
- err = check_reg_arg(env, insn->dst_reg, DST_OP_NO_MARK);
- err = err ?: adjust_scalar_min_max_vals(env, insn,
- &regs[insn->dst_reg],
- regs[insn->dst_reg]);
+ if (__is_pointer_value(false, &regs[insn->dst_reg])) {
+ err = check_reg_arg(env, insn->dst_reg, DST_OP);
+ } else {
+ err = check_reg_arg(env, insn->dst_reg,
+ DST_OP_NO_MARK);
+ err = err ?:
+ adjust_scalar_min_max_vals(
+ env, insn,
+ &regs[insn->dst_reg],
+ regs[insn->dst_reg]);
+ }
} else {
err = check_reg_arg(env, insn->dst_reg, DST_OP);
}

I'll just wait for other developer or Alexei, in case they have any
feedback before sending a v3.

--
Regards,
listout

Brahmajit Das

unread,
Sep 25, 2025, 9:56:28 PM (5 days ago) Sep 25
to KaFai Wan, Alexei Starovoitov, syzbot+d36d5a...@syzkaller.appspotmail.com, Andrii Nakryiko, Alexei Starovoitov, bpf, Daniel Borkmann, Eduard, Hao Luo, John Fastabend, Jiri Olsa, KP Singh, LKML, Martin KaFai Lau, Stanislav Fomichev, Song Liu, syzkaller-bugs, Yonghong Song
Just my 2 cents, thought this looked cleaner

--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -15497,7 +15497,8 @@ static int check_alu_op(struct bpf_verifier_env *env, struct bpf_insn *insn)
if (err)
return err;

- if (is_pointer_value(env, insn->dst_reg)) {
+ if (is_pointer_value(env, insn->dst_reg) ||
+ __is_pointer_value(false, &regs[insn->dst_reg])) {
verbose(env, "R%d pointer arithmetic prohibited\n",
insn->dst_reg);
return -EACCES;

--
Regards,
listout

wan kafai

unread,
Sep 26, 2025, 6:05:45 AM (5 days ago) Sep 26
to Brahmajit Das, KaFai Wan, Alexei Starovoitov, syzbot+d36d5a...@syzkaller.appspotmail.com, Andrii Nakryiko, Alexei Starovoitov, bpf, Daniel Borkmann, Eduard, Hao Luo, John Fastabend, Jiri Olsa, KP Singh, LKML, Martin KaFai Lau, Stanislav Fomichev, Song Liu, syzkaller-bugs, Yonghong Song
On 25.09.2025 23:31, KaFai Wan wrote:
...
> We can use __is_pointer_value to check if the register type is a
> pointer. For pointers, we check as before (before checking BPF_NEG
> separately), and for scalars, it remains unchanged. Perhaps this way we
> can fix the error.
>
> if (opcode == BPF_NEG) {
>        if (__is_pointer_value(false, &regs[insn->dst_reg])) {
>                err = check_reg_arg(env, insn->dst_reg, DST_OP);
>        } else {
>                err = check_reg_arg(env, insn->dst_reg,
> DST_OP_NO_MARK);
>                err = err ?: adjust_scalar_min_max_vals(env, insn,
>                                                &regs[insn->dst_reg],
>                                                regs[insn->dst_reg]);
>        }
> } else {
>
>
> --
> Thanks,
> KaFai

Yep, that works.
OK.
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -15505,10 +15505,17 @@ static int check_alu_op(struct bpf_verifier_env *env, struct bpf_insn *insn)

                /* check dest operand */
                if (opcode == BPF_NEG) {
-                       err = check_reg_arg(env, insn->dst_reg, DST_OP_NO_MARK);
-                       err = err ?: adjust_scalar_min_max_vals(env, insn,
-                                                        &regs[insn->dst_reg],
-                                                        regs[insn->dst_reg]);
+                       if (__is_pointer_value(false, &regs[insn->dst_reg])) {
+                               err = check_reg_arg(env, insn->dst_reg, DST_OP);
+                       } else {
+                               err = check_reg_arg(env, insn->dst_reg,
+                                                   DST_OP_NO_MARK);
+                               err = err   ?:
+                                             adjust_scalar_min_max_vals(
+                                                     env, insn,
+                                                     &regs[insn->dst_reg],
+                                                     regs[insn->dst_reg]);
+                       }
                } else {
                        err = check_reg_arg(env, insn->dst_reg, DST_OP);
                }
We can make code cleaner.

                if (opcode == BPF_NEG && !__is_pointer_value(false, &regs[insn->dst_reg])) {
                        err = check_reg_arg(env, insn->dst_reg, DST_OP_NO_MARK);
                        err = err ?: adjust_scalar_min_max_vals(env, insn,
                                                         &regs[insn->dst_reg],
                                                         regs[insn->dst_reg]);
                } else {
                        err = check_reg_arg(env, insn->dst_reg, DST_OP);
                }
I'll just wait for other developer or Alexei, in case they have any
feedback before sending a v3.
You should add a Fixes label in the commit log and add selftest for it in V3. 
Fixes label is Fixes: aced132599b3 ("bpf: Add range tracking for BPF_NEG")
For selftest you may check the verifier_value_illegal_alu.c and other files.  

The code in your next post would change the  behavior of BPF_NEG and 
BPF_END, you can run the selftest to check that.
--
Regards,
listout

KaFai Wan

unread,
Sep 26, 2025, 6:37:10 AM (5 days ago) Sep 26
to Brahmajit Das, Alexei Starovoitov, syzbot+d36d5a...@syzkaller.appspotmail.com, Andrii Nakryiko, Alexei Starovoitov, bpf, Daniel Borkmann, Eduard, Hao Luo, John Fastabend, Jiri Olsa, KP Singh, LKML, Martin KaFai Lau, Stanislav Fomichev, Song Liu, syzkaller-bugs, Yonghong Song
Ok

We can make code cleaner and change just one line for all.

if (opcode == BPF_NEG && !__is_pointer_value(false, &regs[insn-
>dst_reg])) {


err = check_reg_arg(env, insn->dst_reg, DST_OP_NO_MARK);
err = err ?: adjust_scalar_min_max_vals(env, insn,
&regs[insn->dst_reg],
regs[insn->dst_reg]);
} else {

err = check_reg_arg(env, insn->dst_reg, DST_OP);
}

>
> I'll just wait for other developer or Alexei, in case they have any
> feedback before sending a v3.
>

You should add a Fixes label in the commit log and add selftest for it


in V3. 
Fixes label is Fixes: aced132599b3 ("bpf: Add range tracking for
BPF_NEG")

For selftest you may check the test in verifier_value_illegal_alu.c and
other files.

The code in your next post would change the behavior of BPF_NEG and
BPF_END, you can run the selftest to check that.


The email I sent last time was rejected by the mail server because it
was in HTML format,sorry for that.
--
Thanks,
KaFai

syzbot

unread,
Sep 29, 2025, 2:23:05 PM (2 days ago) Sep 29
to alexei.st...@gmail.com, and...@kernel.org, a...@kernel.org, b...@vger.kernel.org, dan...@iogearbox.net, edd...@gmail.com, hao...@google.com, john.fa...@gmail.com, jo...@kernel.org, kafa...@hotmail.com, kafa...@linux.dev, kps...@kernel.org, linux-...@vger.kernel.org, lis...@listout.xyz, marti...@linux.dev, net...@vger.kernel.org, s...@fomichev.me, so...@kernel.org, syzkall...@googlegroups.com, yongho...@linux.dev
syzbot has bisected this issue to:

commit aced132599b3c8884c050218d4c48eef203678f6
Author: Song Liu <so...@kernel.org>
Date: Wed Jun 25 16:40:24 2025 +0000

bpf: Add range tracking for BPF_NEG

bisection log: https://syzkaller.appspot.com/x/bisect.txt?x=13931ae2580000
start commit: bf40f4b87761 Merge tag 'probes-fixes-v6.17-rc7' of git://g..
git tree: bpf
final oops: https://syzkaller.appspot.com/x/report.txt?x=10531ae2580000
console output: https://syzkaller.appspot.com/x/log.txt?x=17931ae2580000
kernel config: https://syzkaller.appspot.com/x/.config?x=4d8792ecb6308d0f
dashboard link: https://syzkaller.appspot.com/bug?extid=d36d5ae81e1b0a53ef58
syz repro: https://syzkaller.appspot.com/x/repro.syz?x=16010942580000
C reproducer: https://syzkaller.appspot.com/x/repro.c?x=12caeae2580000

Reported-by: syzbot+d36d5a...@syzkaller.appspotmail.com
Fixes: aced132599b3 ("bpf: Add range tracking for BPF_NEG")

For information about bisection process see: https://goo.gl/tpsmEJ#bisection

Brahmajit Das

unread,
Sep 30, 2025, 2:22:21 PM (12 hours ago) Sep 30
to KaFai Wan, Alexei Starovoitov, syzbot+d36d5a...@syzkaller.appspotmail.com, Andrii Nakryiko, Alexei Starovoitov, bpf, Daniel Borkmann, Eduard, Hao Luo, John Fastabend, Jiri Olsa, KP Singh, LKML, Martin KaFai Lau, Stanislav Fomichev, Song Liu, syzkaller-bugs, Yonghong Song
On 26.09.2025 18:36, KaFai Wan wrote:
> On Fri, 2025-09-26 at 06:34 +0530, Brahmajit Das wrote:
> > On 25.09.2025 23:31, KaFai Wan wrote:
> > > On Wed, 2025-09-24 at 23:58 +0530, Brahmajit Das wrote:
> > > > On 25.09.2025 01:38, KaFai Wan wrote:
> > > > > On Wed, 2025-09-24 at 21:10 +0530, Brahmajit Das wrote:
> > > > > > On 24.09.2025 09:32, Alexei Starovoitov wrote:
> > > > > > > On Wed, Sep 24, 2025 at 1:43 AM Brahmajit Das
> > > > > > > <lis...@listout.xyz>
> > > > > > > wrote:
> > > > > > > >
> > > > > > > > Syzkaller reported a general protection fault due to a
> > > > > > > > NULL
> > > > > > > > pointer
> > > > > > > > dereference in print_reg_state() when accessing reg-
> > > > > > > > >map_ptr
> > > > > > > > without
> > > > > > > > checking if it is NULL.
> > > > > > > >
...snip...
>
> You should add a Fixes label in the commit log and add selftest for it
> in V3. 
> Fixes label is Fixes: aced132599b3 ("bpf: Add range tracking for
> BPF_NEG")
> For selftest you may check the test in verifier_value_illegal_alu.c and
> other files.
>
> The code in your next post would change the behavior of BPF_NEG and
> BPF_END, you can run the selftest to check that.
>

KaFai, I'm quite new to kernel development. I'm been trying to write a
selftest for this unfortunately been having a hard time. I would really
appreciate some help. For now I tried to create on from the initial test
you used to verify this bug i.e. r0 -= r0.

I have tried testing my changes via sending a pull request on the
kernel-patches/bpf repository, but seems like it's failing.
My pull request: https://github.com/kernel-patches/bpf/pull/9900

--
Regards,
listout

KaFai Wan

unread,
1:08 AM (1 hour ago) 1:08 AM
to Brahmajit Das, Alexei Starovoitov, syzbot+d36d5a...@syzkaller.appspotmail.com, Andrii Nakryiko, Alexei Starovoitov, bpf, Daniel Borkmann, Eduard, Hao Luo, John Fastabend, Jiri Olsa, KP Singh, LKML, Martin KaFai Lau, Stanislav Fomichev, Song Liu, syzkaller-bugs, Yonghong Song
The attachment is the patch for selftest, you can apply it.

The patch#1 in your PR, Add the Oops call trace or the Closes label in commit
log could be better.

Closes: https://lore.kernel.org/all/68d26227.a70a022...@google.com/
--
Thanks,
KaFai
0001-selftests-bpf-Add-test-for-BPF_NEG-alu-on-CONST_PTR_.patch
Reply all
Reply to author
Forward
0 new messages