In the Linux kernel, the following vulnerability has been resolved:
bpf: Fix tailcallreachable rejection for interpreter when jit failed
During testing of f263a81451c1 ("bpf: Track subprog poke descriptors correctly and fix use-after-free") under various failure conditions, for example, when jit_subprogs() fails and tries to clean up the program to be run under the interpreter, we ran into the following freeze:
[...] #127/8 tailcallbpf2bpf3:FAIL [...] [ 92.041251] BUG: KASAN: slab-out-of-bounds in bpfprogrun+0x1b9d/0x2e20 [ 92.042408] Read of size 8 at addr ffff88800da67f68 by task testprogs/682 [ 92.043707] [ 92.044030] CPU: 1 PID: 682 Comm: testprogs Tainted: G O 5.13.0-53301-ge6c08cb33a30-dirty #87 [ 92.045542] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.13.0-1ubuntu1 04/01/2014 [ 92.046785] Call Trace: [ 92.047171] ? _bpfprogrunargs64+0xc0/0xc0 [ 92.047773] ? _bpfprogrunargs32+0x8b/0xb0 [ 92.048389] ? _bpfprogrunargs64+0xc0/0xc0 [ 92.049019] ? ktimeget+0x117/0x130 [...] // few hundred [similar] lines more [ 92.659025] ? ktimeget+0x117/0x130 [ 92.659845] ? _bpfprogrunargs64+0xc0/0xc0 [ 92.660738] ? _bpfprogrunargs32+0x8b/0xb0 [ 92.661528] ? _bpfprogrunargs64+0xc0/0xc0 [ 92.662378] ? printusagebug+0x50/0x50 [ 92.663221] ? printusagebug+0x50/0x50 [ 92.664077] ? bpfksymfind+0x9c/0xe0 [ 92.664887] ? ktimeget+0x117/0x130 [ 92.665624] ? kerneltextaddress+0xf5/0x100 [ 92.666529] ? _kerneltextaddress+0xe/0x30 [ 92.667725] ? unwindgetreturnaddress+0x2f/0x50 [ 92.668854] ? bpfprogrun+0x15d4/0x2e20 [ 92.670185] ? ktimeget+0x117/0x130 [ 92.671130] ? bpfprogrunargs64+0xc0/0xc0 [ 92.672020] ? _bpfprogrunargs32+0x8b/0xb0 [ 92.672860] ? _bpfprogrunargs64+0xc0/0xc0 [ 92.675159] ? ktimeget+0x117/0x130 [ 92.677074] ? lockisheldtype+0xd5/0x130 [ 92.678662] ? _bpfprogrun+0x15d4/0x2e20 [ 92.680046] ? ktimeget+0x117/0x130 [ 92.681285] ? _bpfprogrun32+0x6b/0x90 [ 92.682601] ? _bpfprogrun64+0x90/0x90 [ 92.683636] ? lockdowngrade+0x370/0x370 [ 92.684647] ? markheldlocks+0x44/0x90 [ 92.685652] ? ktimeget+0x117/0x130 [ 92.686752] ? lockdephardirqson+0x79/0x100 [ 92.688004] ? ktimeget+0x117/0x130 [ 92.688573] ? _cantmigrate+0x2b/0x80 [ 92.689192] ? bpftestrun+0x2f4/0x510 [ 92.689869] ? bpftesttimercontinue+0x1c0/0x1c0 [ 92.690856] ? rcureadlockbhheld+0x90/0x90 [ 92.691506] ? _kasanslaballoc+0x61/0x80 [ 92.692128] ? ethtypetrans+0x128/0x240 [ 92.692737] ? _buildskb+0x46/0x50 [ 92.693252] ? bpfprogtestrunskb+0x65e/0xc50 [ 92.693954] ? bpfprogtestrunrawtp+0x2d0/0x2d0 [ 92.694639] ? _fgetlight+0xa1/0x100 [ 92.695162] ? bpfproginc+0x23/0x30 [ 92.695685] ? _sysbpf+0xb40/0x2c80 [ 92.696324] ? bpflinkgetfromfd+0x90/0x90 [ 92.697150] ? markheldlocks+0x24/0x90 [ 92.698007] ? lockdephardirqsonprepare+0x124/0x220 [ 92.699045] ? finishtaskswitch+0xe6/0x370 [ 92.700072] ? lockdephardirqson+0x79/0x100 [ 92.701233] ? finishtaskswitch+0x11d/0x370 [ 92.702264] ? _switchto+0x2c0/0x740 [ 92.703148] ? markheldlocks+0x24/0x90 [ 92.704155] ? _x64sysbpf+0x45/0x50 [ 92.705146] ? dosyscall64+0x35/0x80 [ 92.706953] ? entrySYSCALL64afterhwframe+0x44/0xae [...]
Turns out that the program rejection from e411901c0b77 ("bpf: allow for tailcalls in BPF subprograms for x64 JIT") is buggy since env->prog->aux->tailcallreachable is never true. Commit ebf7d1f508a7 ("bpf, x64: rework pro/epilogue and tailcall handling in JIT") added a tracker into checkmaxstackdepth() which propagates the tailcall_reachable condition throughout the subprograms. This info is then assigned to the subprogram's ---truncated---