In the Linux kernel, the following vulnerability has been resolved:
bpf: add missing checkfuncargregoff() to prevent out-of-bounds memory accesses
Currently, it's possible to pass in a modified CONSTPTRTODYNPTR to a global function as an argument. The adverse effects of this is that BPF helpers can continue to make use of this modified CONSTPTRTODYNPTR from within the context of the global function, which can unintentionally result in out-of-bounds memory accesses and therefore compromise overall system stability i.e.
[ 244.157771] BUG: KASAN: slab-out-of-bounds in bpfdynptrdata+0x137/0x140 [ 244.161345] Read of size 8 at addr ffff88810914be68 by task testprogs/302 [ 244.167151] CPU: 0 PID: 302 Comm: testprogs Tainted: G O E 6.10.0-rc3-00131-g66b586715063 #533 [ 244.174318] Call Trace: [ 244.175787] <TASK> [ 244.177356] dumpstacklvl+0x66/0xa0 [ 244.179531] printreport+0xce/0x670 [ 244.182314] ? _virtaddrvalid+0x200/0x3e0 [ 244.184908] kasanreport+0xd7/0x110 [ 244.187408] ? bpfdynptrdata+0x137/0x140 [ 244.189714] ? bpfdynptrdata+0x137/0x140 [ 244.192020] bpfdynptrdata+0x137/0x140 [ 244.194264] bpfprogb02a02fdd2bdc5faglobalcallbpfdynptrdata+0x22/0x26 [ 244.198044] bpfprogb0fe7b9d7dc3abdecallbackadjustbpfdynptrregoff+0x1f/0x23 [ 244.202136] bpfuserringbufdrain+0x2c7/0x570 [ 244.204744] ? 0xffffffffc0009e58 [ 244.206593] ? _pfxbpfuserringbufdrain+0x10/0x10 [ 244.209795] bpfprog33ab33f6a804ba2duserringbufcallbackconstptrtodynptrregoff+0x47/0x4b [ 244.215922] bpftrampoline6442502480+0x43/0xe3 [ 244.218691] _x64sysprlimit64+0x9/0xf0 [ 244.220912] dosyscall64+0xc1/0x1d0 [ 244.223043] entrySYSCALL64afterhwframe+0x77/0x7f [ 244.226458] RIP: 0033:0x7ffa3eb8f059 [ 244.228582] Code: 08 89 e8 5b 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 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d 8f 1d 0d 00 f7 d8 64 89 01 48 [ 244.241307] RSP: 002b:00007ffa3e9c6eb8 EFLAGS: 00000206 ORIG_RAX: 000000000000012e [ 244.246474] RAX: ffffffffffffffda RBX: 00007ffa3e9c7cdc RCX: 00007ffa3eb8f059 [ 244.250478] RDX: 00007ffa3eb162b4 RSI: 0000000000000000 RDI: 00007ffa3e9c7fb0 [ 244.255396] RBP: 00007ffa3e9c6ed0 R08: 00007ffa3e9c76c0 R09: 0000000000000000 [ 244.260195] R10: 0000000000000000 R11: 0000000000000206 R12: ffffffffffffff80 [ 244.264201] R13: 000000000000001c R14: 00007ffc5d6b4260 R15: 00007ffa3e1c7000 [ 244.268303] </TASK>
Add a checkfuncargregoff() to the path in which the BPF verifier verifies the arguments of global function arguments, specifically those which take an argument of type ARGPTRTODYNPTR | MEMRDONLY. Also, processdynptrfunc() doesn't appear to perform any explicit and strict type matching on the supplied register type, so let's also enforce that a register either type PTRTOSTACK or CONSTPTRTO_DYNPTR is by the caller.