In the Linux kernel, the following vulnerability has been resolved:
BPF: Fix potential bad pointer dereference in bpfsysbpf()
The bpfsysbpf() helper function allows an eBPF program to load another eBPF program from within the kernel. In this case the argument union bpfattr pointer (as well as the insns and license pointers inside) is a kernel address instead of a userspace address (which is the case of a usual bpf() syscall). To make the memory copying process in the syscall work in both cases, bpfptrt was introduced to wrap around the pointer and distinguish its origin. Specifically, when copying memory contents from a bpfptrt, a copyfrom_user() is performed in case of a userspace address and a memcpy() is performed for a kernel address.
This can lead to problems because the in-kernel pointer is never checked for validity. The problem happens when an eBPF syscall program tries to call bpfsysbpf() to load a program but provides a bad insns pointer -- say 0xdeadbeef -- in the bpfattr union. The helper calls _sysbpf() which would then call bpfprogload() to load the program. bpfprogload() is responsible for copying the eBPF instructions to the newly allocated memory for the program; it creates a kernel bpfptrt for insns and invokes copyfrombpfptr(). Internally, all bpfptrt operations are backed by the corresponding sockptrt operations, which performs direct memcpy() on kernel pointers for copyfrom/strncpyfrom operations. Therefore, the code is always happy to dereference the bad pointer to trigger a un-handle-able page fault and in turn an oops. However, this is not supposed to happen because at that point the eBPF program is already verified and should not cause a memory error.
Sample KASAN trace:
[ 25.685056][ T228] ================================================================== [ 25.685680][ T228] BUG: KASAN: user-memory-access in copyfrombpfptr+0x21/0x30 [ 25.686210][ T228] Read of size 80 at addr 00000000deadbeef by task poc/228 [ 25.686732][ T228] [ 25.686893][ T228] CPU: 3 PID: 228 Comm: poc Not tainted 5.19.0-rc7 #7 [ 25.687375][ T228] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS d55cb5a 04/01/2014 [ 25.687991][ T228] Call Trace: [ 25.688223][ T228] <TASK> [ 25.688429][ T228] dumpstacklvl+0x73/0x9e [ 25.688747][ T228] printreport+0xea/0x200 [ 25.689061][ T228] ? copyfrombpfptr+0x21/0x30 [ 25.689401][ T228] ? _printk+0x54/0x6e [ 25.689693][ T228] ? _rawspinlockirqsave+0x70/0xd0 [ 25.690071][ T228] ? copyfrombpfptr+0x21/0x30 [ 25.690412][ T228] kasanreport+0xb5/0xe0 [ 25.690716][ T228] ? copyfrombpfptr+0x21/0x30 [ 25.691059][ T228] kasancheckrange+0x2bd/0x2e0 [ 25.691405][ T228] ? copyfrombpfptr+0x21/0x30 [ 25.691734][ T228] memcpy+0x25/0x60 [ 25.692000][ T228] copyfrombpfptr+0x21/0x30 [ 25.692328][ T228] bpfprogload+0x604/0x9e0 [ 25.692653][ T228] ? capcapable+0xb4/0xe0 [ 25.692956][ T228] ? securitycapable+0x4f/0x70 [ 25.693324][ T228] _sysbpf+0x3af/0x580 [ 25.693635][ T228] bpfsysbpf+0x45/0x240 [ 25.693937][ T228] bpfprogf0ec79a5a3caca46bpffunc1+0xa2/0xbd [ 25.694394][ T228] bpfprogrunpinoncpu+0x2f/0xb0 [ 25.694756][ T228] bpfprogtestrunsyscall+0x146/0x1c0 [ 25.695144][ T228] bpfprogtestrun+0x172/0x190 [ 25.695487][ T228] _sysbpf+0x2c5/0x580 [ 25.695776][ T228] _x64sysbpf+0x3a/0x50 [ 25.696084][ T228] dosyscall64+0x60/0x90 [ 25.696393][ T228] ? fpregsassertstateconsistent+0x50/0x60 [ 25.696815][ T228] ? exittousermodeprepare+0x36/0xa0 [ 25.697202][ T228] ? syscallexittousermode+0x20/0x40 [ 25.697586][ T228] ? dosyscall64+0x6e/0x90 [ 25.697899][ T228] entrySYSCALL64after_hwframe+0x63/0xcd [ 25.698312][ T228] RIP: 0033:0x7f6d543fb759 [ 25.698624][ T228] Code: 08 5b 89 e8 5d c3 66 2e 0f 1f 84 00 00 00 00 00 90 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d ---truncated---