* Re: BUG: null pointer dereference in seccomp
[not found] <CANikGpeQuBKj89rTkaAs5ADrz0+YLQ54g-0CshYzE3h06G0U5g@mail.gmail.com>
@ 2024-08-29 0:38 ` Kees Cook
2024-08-29 15:49 ` Jann Horn
2024-08-29 20:09 ` Jann Horn
0 siblings, 2 replies; 3+ messages in thread
From: Kees Cook @ 2024-08-29 0:38 UTC (permalink / raw)
To: Juefei Pu; +Cc: luto, wad, linux-kernel, linux-hardening, bpf
On Tue, Aug 27, 2024 at 09:09:49PM -0700, Juefei Pu wrote:
> Hello,
> We found the following null-pointer-dereference issue using syzkaller
> on Linux v6.10.
In seccomp! Yikes.
> Unfortunately, the syzkaller failed to generate a reproducer.
That's a bummer.
> But at least we have the report:
>
> Oops: general protection fault, probably for non-canonical address
> 0xdffffc0000000006: 0000 [#1] PREEMPT SMP KASAN PTI
> KASAN: null-ptr-deref in range [0x0000000000000030-0x0000000000000037]
> CPU: 0 PID: 4493 Comm: systemd-journal Not tainted 6.10.0 #13
> Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.15.0-1 04/01/2014
> RIP: 0010:__bpf_prog_run include/linux/filter.h:691 [inline]
This doesn't look like a NULL deref, this looks like a corrupted
pointer: 0xdffffc0000000006. Is prog bad or dfunc bad? I assume the
former, as dfunc is hard-coded below...
ret = dfunc(ctx, prog->insnsi, prog->bpf_func);
> RIP: 0010:bpf_prog_run include/linux/filter.h:698 [inline]
return __bpf_prog_run(prog, ctx, bpf_dispatcher_nop_func);
> RIP: 0010:bpf_prog_run_pin_on_cpu include/linux/filter.h:715 [inline]
ret = bpf_prog_run(prog, ctx);
> RIP: 0010:seccomp_run_filters+0x17a/0x3f0 kernel/seccomp.c:426
u32 cur_ret = bpf_prog_run_pin_on_cpu(f->prog, sd);
> Code: 00 00 e8 99 36 d2 ff 0f 1f 44 00 00 e8 cf 58 ff ff 48 8d 5d 48
> 48 83 c5 30 48 89 e8 48 c1 e8 03 48 b9 00 00 00 00 00 fc ff df <80> 3c
> 08 00 74 08 48 89 ef e8 c8 63 62 00 4c 8b 5d 00 48 8b 3c 24
> RSP: 0018:ffffc90002cb7be0 EFLAGS: 00010206
> RAX: 0000000000000006 RBX: 0000000000000048 RCX: dffffc0000000000
> RDX: 0000000000000000 RSI: 00000000000002a4 RDI: ffffffff8b517360
> RBP: 0000000000000030 R08: ffffffff8191f8eb R09: 1ffff11004039e86
> R10: dffffc0000000000 R11: ffffffffa00016d0 R12: 000000007fff0000
> R13: ffff88801f84a800 R14: ffffc90002cb7df0 R15: 000000007fff0000
> FS: 00007f897e849900(0000) GS:ffff888063a00000(0000) knlGS:0000000000000000
> CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
> CR2: 00007f897d771b08 CR3: 00000000195fe000 CR4: 0000000000350ef0
> DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
> DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
> Call Trace:
> <TASK>
> __seccomp_filter+0x46f/0x1c70 kernel/seccomp.c:1222
> syscall_trace_enter+0xa4/0x140 kernel/entry/common.c:52
> syscall_enter_from_user_mode_work include/linux/entry-common.h:168 [inline]
> syscall_enter_from_user_mode include/linux/entry-common.h:198 [inline]
> do_syscall_64+0x5d/0x150 arch/x86/entry/common.c:79
> entry_SYSCALL_64_after_hwframe+0x67/0x6f
Has anything changed in BPF in this area lately?
> RIP: 0033:0x7f897ed171e4
> Code: 84 00 00 00 00 00 44 89 54 24 0c e8 36 58 f9 ff 44 8b 54 24 0c
> 44 89 e2 48 89 ee 41 89 c0 bf 9c ff ff ff b8 01 01 00 00 0f 05 <48> 3d
> 00 f0 ff ff 77 34 44 89 c7 89 44 24 0c e8 68 58 f9 ff 8b 44
> RSP: 002b:00007ffd4ae74a60 EFLAGS: 00000293 ORIG_RAX: 0000000000000101
> RAX: ffffffffffffffda RBX: 00005627cd785ed0 RCX: 00007f897ed171e4
> RDX: 0000000000290000 RSI: 00007f897f010d0a RDI: 00000000ffffff9c
> RBP: 00007f897f010d0a R08: 0000000000000000 R09: 0034353132303865
> R10: 0000000000000000 R11: 0000000000000293 R12: 0000000000290000
> R13: 00007ffd4ae74d20 R14: 0000000000000000 R15: 00007ffd4ae74e28
> </TASK>
> Modules linked in:
> ---[ end trace 0000000000000000 ]---
> RIP: 0010:__bpf_prog_run include/linux/filter.h:691 [inline]
> RIP: 0010:bpf_prog_run include/linux/filter.h:698 [inline]
> RIP: 0010:bpf_prog_run_pin_on_cpu include/linux/filter.h:715 [inline]
> RIP: 0010:seccomp_run_filters+0x17a/0x3f0 kernel/seccomp.c:426
> Code: 00 00 e8 99 36 d2 ff 0f 1f 44 00 00 e8 cf 58 ff ff 48 8d 5d 48
> 48 83 c5 30 48 89 e8 48 c1 e8 03 48 b9 00 00 00 00 00 fc ff df <80> 3c
> 08 00 74 08 48 89 ef e8 c8 63 62 00 4c 8b 5d 00 48 8b 3c 24
> RSP: 0018:ffffc90002cb7be0 EFLAGS: 00010206
> RAX: 0000000000000006 RBX: 0000000000000048 RCX: dffffc0000000000
> RDX: 0000000000000000 RSI: 00000000000002a4 RDI: ffffffff8b517360
> RBP: 0000000000000030 R08: ffffffff8191f8eb R09: 1ffff11004039e86
> R10: dffffc0000000000 R11: ffffffffa00016d0 R12: 000000007fff0000
> R13: ffff88801f84a800 R14: ffffc90002cb7df0 R15: 000000007fff0000
> FS: 00007f897e849900(0000) GS:ffff888063a00000(0000) knlGS:0000000000000000
> CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
> CR2: 00007f521f8ca000 CR3: 00000000195fe000 CR4: 0000000000350ef0
> DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
> DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
> ----------------
> Code disassembly (best guess):
> 0: 00 00 add %al,(%rax)
> 2: e8 99 36 d2 ff call 0xffd236a0
> 7: 0f 1f 44 00 00 nopl 0x0(%rax,%rax,1)
> c: e8 cf 58 ff ff call 0xffff58e0
> 11: 48 8d 5d 48 lea 0x48(%rbp),%rbx
> 15: 48 83 c5 30 add $0x30,%rbp
> 19: 48 89 e8 mov %rbp,%rax
> 1c: 48 c1 e8 03 shr $0x3,%rax
> 20: 48 b9 00 00 00 00 00 movabs $0xdffffc0000000000,%rcx
> 27: fc ff df
> * 2a: 80 3c 08 00 cmpb $0x0,(%rax,%rcx,1) <-- trapping instruction
> 2e: 74 08 je 0x38
> 30: 48 89 ef mov %rbp,%rdi
> 33: e8 c8 63 62 00 call 0x626400
> 38: 4c 8b 5d 00 mov 0x0(%rbp),%r11
> 3c: 48 8b 3c 24 mov (%rsp),%rdi
What's the movabs? I don't have anything like that in my vmlinux binary
output. Is this KASAN perhaps?
Regardless, I don't see how prog could be NULL. :( It shouldn't be
possible without some kind of major refcounting bug.
-Kees
--
Kees Cook
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: BUG: null pointer dereference in seccomp
2024-08-29 0:38 ` BUG: null pointer dereference in seccomp Kees Cook
@ 2024-08-29 15:49 ` Jann Horn
2024-08-29 20:09 ` Jann Horn
1 sibling, 0 replies; 3+ messages in thread
From: Jann Horn @ 2024-08-29 15:49 UTC (permalink / raw)
To: Kees Cook; +Cc: Juefei Pu, luto, wad, linux-kernel, linux-hardening, bpf
On Thu, Aug 29, 2024 at 2:38 AM Kees Cook <kees@kernel.org> wrote:
> On Tue, Aug 27, 2024 at 09:09:49PM -0700, Juefei Pu wrote:
> > Hello,
> > We found the following null-pointer-dereference issue using syzkaller
> > on Linux v6.10.
>
> In seccomp! Yikes.
>
> > Unfortunately, the syzkaller failed to generate a reproducer.
>
> That's a bummer.
>
> > But at least we have the report:
> >
> > Oops: general protection fault, probably for non-canonical address
> > 0xdffffc0000000006: 0000 [#1] PREEMPT SMP KASAN PTI
> > KASAN: null-ptr-deref in range [0x0000000000000030-0x0000000000000037]
> > CPU: 0 PID: 4493 Comm: systemd-journal Not tainted 6.10.0 #13
> > Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.15.0-1 04/01/2014
> > RIP: 0010:__bpf_prog_run include/linux/filter.h:691 [inline]
>
> This doesn't look like a NULL deref, this looks like a corrupted
> pointer: 0xdffffc0000000006.
No, it really is a NULL deref - in a non-KASAN build, you'd see a page
fault at virtual address 0x30. KASAN builds with inline
instrumentation cause a GPF on NULL deref because they try to first
check the KASAN shadow mapping for that address, and applying the
shadow address calculation to NULL (or addresses in the low address
space half) gives non-canonical addresses.
This line directly below the oops message is supposed to point this
out (it works by decoding the faulting instruction, calculating the
effective address of the access, and then having KASAN calculate
backwards from the shadow address what the original address could have
been):
KASAN: null-ptr-deref in range [0x0000000000000030-0x0000000000000037]
> Is prog bad or dfunc bad? I assume the
> former, as dfunc is hard-coded below...
>
> ret = dfunc(ctx, prog->insnsi, prog->bpf_func);
>
> > RIP: 0010:bpf_prog_run include/linux/filter.h:698 [inline]
>
> return __bpf_prog_run(prog, ctx, bpf_dispatcher_nop_func);
>
> > RIP: 0010:bpf_prog_run_pin_on_cpu include/linux/filter.h:715 [inline]
>
> ret = bpf_prog_run(prog, ctx);
>
> > RIP: 0010:seccomp_run_filters+0x17a/0x3f0 kernel/seccomp.c:426
>
> u32 cur_ret = bpf_prog_run_pin_on_cpu(f->prog, sd);
>
> > Code: 00 00 e8 99 36 d2 ff 0f 1f 44 00 00 e8 cf 58 ff ff 48 8d 5d 48
> > 48 83 c5 30 48 89 e8 48 c1 e8 03 48 b9 00 00 00 00 00 fc ff df <80> 3c
> > 08 00 74 08 48 89 ef e8 c8 63 62 00 4c 8b 5d 00 48 8b 3c 24
> > RSP: 0018:ffffc90002cb7be0 EFLAGS: 00010206
> > RAX: 0000000000000006 RBX: 0000000000000048 RCX: dffffc0000000000
> > RDX: 0000000000000000 RSI: 00000000000002a4 RDI: ffffffff8b517360
> > RBP: 0000000000000030 R08: ffffffff8191f8eb R09: 1ffff11004039e86
> > R10: dffffc0000000000 R11: ffffffffa00016d0 R12: 000000007fff0000
> > R13: ffff88801f84a800 R14: ffffc90002cb7df0 R15: 000000007fff0000
> > FS: 00007f897e849900(0000) GS:ffff888063a00000(0000) knlGS:0000000000000000
> > CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
> > CR2: 00007f897d771b08 CR3: 00000000195fe000 CR4: 0000000000350ef0
> > DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
> > DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
> > Call Trace:
> > <TASK>
> > __seccomp_filter+0x46f/0x1c70 kernel/seccomp.c:1222
> > syscall_trace_enter+0xa4/0x140 kernel/entry/common.c:52
> > syscall_enter_from_user_mode_work include/linux/entry-common.h:168 [inline]
> > syscall_enter_from_user_mode include/linux/entry-common.h:198 [inline]
> > do_syscall_64+0x5d/0x150 arch/x86/entry/common.c:79
> > entry_SYSCALL_64_after_hwframe+0x67/0x6f
>
> Has anything changed in BPF in this area lately?
>
> > RIP: 0033:0x7f897ed171e4
> > Code: 84 00 00 00 00 00 44 89 54 24 0c e8 36 58 f9 ff 44 8b 54 24 0c
> > 44 89 e2 48 89 ee 41 89 c0 bf 9c ff ff ff b8 01 01 00 00 0f 05 <48> 3d
> > 00 f0 ff ff 77 34 44 89 c7 89 44 24 0c e8 68 58 f9 ff 8b 44
> > RSP: 002b:00007ffd4ae74a60 EFLAGS: 00000293 ORIG_RAX: 0000000000000101
> > RAX: ffffffffffffffda RBX: 00005627cd785ed0 RCX: 00007f897ed171e4
> > RDX: 0000000000290000 RSI: 00007f897f010d0a RDI: 00000000ffffff9c
> > RBP: 00007f897f010d0a R08: 0000000000000000 R09: 0034353132303865
> > R10: 0000000000000000 R11: 0000000000000293 R12: 0000000000290000
> > R13: 00007ffd4ae74d20 R14: 0000000000000000 R15: 00007ffd4ae74e28
> > </TASK>
> > Modules linked in:
> > ---[ end trace 0000000000000000 ]---
> > RIP: 0010:__bpf_prog_run include/linux/filter.h:691 [inline]
> > RIP: 0010:bpf_prog_run include/linux/filter.h:698 [inline]
> > RIP: 0010:bpf_prog_run_pin_on_cpu include/linux/filter.h:715 [inline]
> > RIP: 0010:seccomp_run_filters+0x17a/0x3f0 kernel/seccomp.c:426
> > Code: 00 00 e8 99 36 d2 ff 0f 1f 44 00 00 e8 cf 58 ff ff 48 8d 5d 48
> > 48 83 c5 30 48 89 e8 48 c1 e8 03 48 b9 00 00 00 00 00 fc ff df <80> 3c
> > 08 00 74 08 48 89 ef e8 c8 63 62 00 4c 8b 5d 00 48 8b 3c 24
> > RSP: 0018:ffffc90002cb7be0 EFLAGS: 00010206
> > RAX: 0000000000000006 RBX: 0000000000000048 RCX: dffffc0000000000
> > RDX: 0000000000000000 RSI: 00000000000002a4 RDI: ffffffff8b517360
> > RBP: 0000000000000030 R08: ffffffff8191f8eb R09: 1ffff11004039e86
> > R10: dffffc0000000000 R11: ffffffffa00016d0 R12: 000000007fff0000
> > R13: ffff88801f84a800 R14: ffffc90002cb7df0 R15: 000000007fff0000
> > FS: 00007f897e849900(0000) GS:ffff888063a00000(0000) knlGS:0000000000000000
> > CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
> > CR2: 00007f521f8ca000 CR3: 00000000195fe000 CR4: 0000000000350ef0
> > DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
> > DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
> > ----------------
> > Code disassembly (best guess):
> > 0: 00 00 add %al,(%rax)
> > 2: e8 99 36 d2 ff call 0xffd236a0
> > 7: 0f 1f 44 00 00 nopl 0x0(%rax,%rax,1)
> > c: e8 cf 58 ff ff call 0xffff58e0
> > 11: 48 8d 5d 48 lea 0x48(%rbp),%rbx
This LEA looks like it's calculating the address of prog->insnsi.
> > 15: 48 83 c5 30 add $0x30,%rbp
> > 19: 48 89 e8 mov %rbp,%rax
> > 1c: 48 c1 e8 03 shr $0x3,%rax
> > 20: 48 b9 00 00 00 00 00 movabs $0xdffffc0000000000,%rcx
> > 27: fc ff df
> > * 2a: 80 3c 08 00 cmpb $0x0,(%rax,%rcx,1) <-- trapping instruction
Here you can see - the access happens at rax+rcx, which is
(rbp>>3)+0xdffffc0000000000. rbp is the actual pointer that will be
accessed; this shift-right-and-add-0xdffffc0000000000 pattern is how
inline KASAN instrumentation determines the shadow address.
> > 2e: 74 08 je 0x38
Normally we jump over the next two instructions, if the KASAN shadow
is 0 (which means fully accessible)...
> > 30: 48 89 ef mov %rbp,%rdi
> > 33: e8 c8 63 62 00 call 0x626400
... continue here:
> > 38: 4c 8b 5d 00 mov 0x0(%rbp),%r11
And here's the actual access to rbp, which is probably loading the
prog->bpf_func.
> > 3c: 48 8b 3c 24 mov (%rsp),%rdi
>
> What's the movabs? I don't have anything like that in my vmlinux binary
> output. Is this KASAN perhaps?
Yes, inline KASAN.
>
> Regardless, I don't see how prog could be NULL. :( It shouldn't be
> possible without some kind of major refcounting bug.
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: BUG: null pointer dereference in seccomp
2024-08-29 0:38 ` BUG: null pointer dereference in seccomp Kees Cook
2024-08-29 15:49 ` Jann Horn
@ 2024-08-29 20:09 ` Jann Horn
1 sibling, 0 replies; 3+ messages in thread
From: Jann Horn @ 2024-08-29 20:09 UTC (permalink / raw)
To: Juefei Pu; +Cc: Kees Cook, luto, wad, linux-kernel, linux-hardening, bpf
On Thu, Aug 29, 2024 at 2:38 AM Kees Cook <kees@kernel.org> wrote:
> On Tue, Aug 27, 2024 at 09:09:49PM -0700, Juefei Pu wrote:
> > Hello,
> > We found the following null-pointer-dereference issue using syzkaller
> > on Linux v6.10.
>
> In seccomp! Yikes.
>
> > Unfortunately, the syzkaller failed to generate a reproducer.
>
> That's a bummer.
>
> > But at least we have the report:
> >
> > Oops: general protection fault, probably for non-canonical address
> > 0xdffffc0000000006: 0000 [#1] PREEMPT SMP KASAN PTI
> > KASAN: null-ptr-deref in range [0x0000000000000030-0x0000000000000037]
> > CPU: 0 PID: 4493 Comm: systemd-journal Not tainted 6.10.0 #13
> > Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.15.0-1 04/01/2014
> > RIP: 0010:__bpf_prog_run include/linux/filter.h:691 [inline]
So, the issue can't be that we went through the seccomp filter setup
path properly and the bpf_prog was never actually installed, because
in that case we would've crashed in seccomp_cache_prepare_bitmap().
I'm pretty confused how we could've possibly gotten into this situation...
What kind of test setup are you using - is this QEMU in TCG mode or in
KVM mode? Can you share your vmlinux binary, so we can see if there's
a clue left in the register state of the crash?
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2024-08-29 20:10 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <CANikGpeQuBKj89rTkaAs5ADrz0+YLQ54g-0CshYzE3h06G0U5g@mail.gmail.com>
2024-08-29 0:38 ` BUG: null pointer dereference in seccomp Kees Cook
2024-08-29 15:49 ` Jann Horn
2024-08-29 20:09 ` Jann Horn
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox