Messages in this thread | | | Date | Mon, 20 Dec 2021 08:50:00 -0500 | Subject | Re: [PATCH] bpf: check size before calling kvmalloc | From | George Kennedy <> |
| |
On 12/17/2021 5:45 PM, Daniel Borkmann wrote: > On 12/17/21 7:48 PM, George Kennedy wrote: >> ZERO_SIZE_PTR ((void *)16) is returned by kvmalloc() instead of NULL >> if size is zero. Currently, return values from kvmalloc() are only >> checked for NULL. Before calling kvmalloc() check for size of zero >> and return error if size is zero to avoid the following crash. >> >> BUG: kernel NULL pointer dereference, address: 0000000000000000 >> PGD 1030bd067 P4D 1030bd067 PUD 103497067 PMD 0 >> Oops: 0010 [#1] PREEMPT SMP KASAN NOPTI >> CPU: 1 PID: 15094 Comm: syz-executor344 Not tainted 5.16.0-rc1-syzk #1 >> Hardware name: Red Hat KVM, BIOS >> RIP: 0010:0x0 >> Code: Unable to access opcode bytes at RIP 0xffffffffffffffd6. >> RSP: 0018:ffff888017627b78 EFLAGS: 00010246 >> RAX: 0000000000000000 RBX: ffff8880215d0780 RCX: ffffffff81b63c60 >> RDX: 0000000000000010 RSI: 0000000000000000 RDI: ffff8881035db400 >> RBP: ffff888017627f08 R08: ffffed1003697209 R09: ffffed1003697209 >> R10: ffff88801b4b9043 R11: ffffed1003697208 R12: ffffffff8f15d580 >> R13: 1ffff11002ec4f77 R14: ffff8881035db400 R15: 0000000000000000 >> FS: 00007f62bca78740(0000) GS:ffff888107880000(0000) >> knlGS:0000000000000000 >> CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 >> CR2: ffffffffffffffd6 CR3: 000000002282a000 CR4: 00000000000006e0 >> Call Trace: >> <TASK> >> map_get_next_key kernel/bpf/syscall.c:1279 [inline] >> __sys_bpf+0x384d/0x5b30 kernel/bpf/syscall.c:4612 >> __do_sys_bpf kernel/bpf/syscall.c:4722 [inline] >> __se_sys_bpf kernel/bpf/syscall.c:4720 [inline] >> __x64_sys_bpf+0x7a/0xc0 kernel/bpf/syscall.c:4720 >> do_syscall_x64 arch/x86/entry/common.c:50 [inline] >> do_syscall_64+0x3a/0x80 arch/x86/entry/common.c:80 >> entry_SYSCALL_64_after_hwframe+0x44/0xae >> >> Reported-by: syzkaller <syzkaller@googlegroups.com> >> Signed-off-by: George Kennedy <george.kennedy@oracle.com> > > Could you provide some more details, e.g. which map type is this where we > have to assume zero-sized keys everywhere? > > (Or link to syzkaller report could also work alternatively if public.)
I don't think the report is public. Here's the report and C reproducer:
#ifdef REF Syzkaller hit 'BUG: unable to handle kernel NULL pointer dereference in bpf' bug.
BUG: kernel NULL pointer dereference, address: 0000000000000000 #PF: supervisor instruction fetch in kernel mode #PF: error_code(0x0010) - not-present page PGD 1030bd067 P4D 1030bd067 PUD 103497067 PMD 0 Oops: 0010 [#1] PREEMPT SMP KASAN NOPTI CPU: 1 PID: 15094 Comm: syz-executor344 Not tainted 5.16.0-rc1-syzk #1 Hardware name: Red Hat KVM, BIOS 1.13.0-2.module+el8.3.0+7860+a7792d29 04/01/2014 RIP: 0010:0x0 Code: Unable to access opcode bytes at RIP 0xffffffffffffffd6. RSP: 0018:ffff888017627b78 EFLAGS: 00010246 RAX: 0000000000000000 RBX: ffff8880215d0780 RCX: ffffffff81b63c60 RDX: 0000000000000010 RSI: 0000000000000000 RDI: ffff8881035db400 RBP: ffff888017627f08 R08: ffffed1003697209 R09: ffffed1003697209 R10: ffff88801b4b9043 R11: ffffed1003697208 R12: ffffffff8f15d580 R13: 1ffff11002ec4f77 R14: ffff8881035db400 R15: 0000000000000000 FS: 00007f62bca78740(0000) GS:ffff888107880000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: ffffffffffffffd6 CR3: 000000002282a000 CR4: 00000000000006e0 Call Trace: <TASK> map_get_next_key kernel/bpf/syscall.c:1279 [inline] __sys_bpf+0x384d/0x5b30 kernel/bpf/syscall.c:4612 __do_sys_bpf kernel/bpf/syscall.c:4722 [inline] __se_sys_bpf kernel/bpf/syscall.c:4720 [inline] __x64_sys_bpf+0x7a/0xc0 kernel/bpf/syscall.c:4720 do_syscall_x64 arch/x86/entry/common.c:50 [inline] do_syscall_64+0x3a/0x80 arch/x86/entry/common.c:80 entry_SYSCALL_64_after_hwframe+0x44/0xae RIP: 0033:0x7f62bc36f289 Code: 01 00 48 81 c4 80 00 00 00 e9 f1 fe ff ff 0f 1f 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 8b 0d b7 db 2c 00 f7 d8 64 89 01 48 RSP: 002b:00007ffccaa211e8 EFLAGS: 00000246 ORIG_RAX: 0000000000000141 RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00007f62bc36f289 RDX: 0000000000000020 RSI: 0000000020000080 RDI: 0000000000000004 RBP: 0000000000000000 R08: 0000000000000000 R09: 0000000000000000 R10: 0000000000000000 R11: 0000000000000246 R12: 00000000004006d0 R13: 00007ffccaa212d0 R14: 0000000000000000 R15: 0000000000000000 </TASK> Modules linked in: CR2: 0000000000000000 ---[ end trace d203e5a1836d64aa ]--- RIP: 0010:0x0 Code: Unable to access opcode bytes at RIP 0xffffffffffffffd6. RSP: 0018:ffff888017627b78 EFLAGS: 00010246 RAX: 0000000000000000 RBX: ffff8880215d0780 RCX: ffffffff81b63c60 RDX: 0000000000000010 RSI: 0000000000000000 RDI: ffff8881035db400 RBP: ffff888017627f08 R08: ffffed1003697209 R09: ffffed1003697209 R10: ffff88801b4b9043 R11: ffffed1003697208 R12: ffffffff8f15d580 R13: 1ffff11002ec4f77 R14: ffff8881035db400 R15: 0000000000000000 FS: 00007f62bca78740(0000) GS:ffff888107880000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: ffffffffffffffd6 CR3: 000000002282a000 CR4: 00000000000006e0
Syzkaller reproducer: # {Threaded:false Collide:false Repeat:false RepeatTimes:0 Procs:1 Slowdown:1 Sandbox: Fault:false FaultCall:-1 FaultNth:0 Leak:false NetInjection:false NetDevices:false NetReset:false Cgroups:false BinfmtMisc:false CloseFDs:false KCSAN:false DevlinkPCI:false USB:false VhciInjection:false Wifi:false IEEE802154:false Sysctl:false UseTmpDir:false HandleSegv:false Repro:false Trace:false} r0 = bpf$MAP_CREATE(0x0, &(0x7f0000001480)={0x1e, 0x0, 0x2, 0x2, 0x0, 0x1}, 0x40) bpf$MAP_GET_NEXT_KEY(0x4, &(0x7f0000000080)={r0, 0x0, 0x0}, 0x20)
C reproducer: #endif /* REF */ // autogenerated by syzkaller (https://github.com/google/syzkaller)
#define _GNU_SOURCE
#include <endian.h> #include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/syscall.h> #include <sys/types.h> #include <unistd.h>
#ifndef __NR_bpf #define __NR_bpf 321 #endif
uint64_t r[1] = {0xffffffffffffffff};
int main(void) { syscall(__NR_mmap, 0x1ffff000ul, 0x1000ul, 0ul, 0x32ul, -1, 0ul); syscall(__NR_mmap, 0x20000000ul, 0x1000000ul, 7ul, 0x32ul, -1, 0ul); syscall(__NR_mmap, 0x21000000ul, 0x1000ul, 0ul, 0x32ul, -1, 0ul); intptr_t res = 0; *(uint32_t*)0x20001480 = 0x1e; *(uint32_t*)0x20001484 = 0; *(uint32_t*)0x20001488 = 2; *(uint32_t*)0x2000148c = 2; *(uint32_t*)0x20001490 = 0; *(uint32_t*)0x20001494 = 1; *(uint32_t*)0x20001498 = 0; memset((void*)0x2000149c, 0, 16); *(uint32_t*)0x200014ac = 0; *(uint32_t*)0x200014b0 = -1; *(uint32_t*)0x200014b4 = 0; *(uint32_t*)0x200014b8 = 0; *(uint32_t*)0x200014bc = 0; res = syscall(__NR_bpf, 0ul, 0x20001480ul, 0x40ul); if (res != -1) r[0] = res; *(uint32_t*)0x20000080 = r[0]; *(uint64_t*)0x20000088 = 0; *(uint64_t*)0x20000090 = 0; *(uint64_t*)0x20000098 = 0; syscall(__NR_bpf, 4ul, 0x20000080ul, 0x20ul); return 0; }
George
> > Thanks, > Daniel
| |