eBPF verifier register-limit tracking bug (CVE-2023-2163)¶
backtrack_insn(), register-vs-register conditional'larda source register'ı precise işaretlemeyi atladı; bu yüzden verifier eşdeğer sandığı güvensiz bir path'i prune etti — arbitrary kernel R/W (Google Buzzer/fuzzing bulgusu).
Mechanism¶
Note
jmp/jmp32 instruction class'ı için backtrack_insn() (kernel/bpf/verifier.c içindeki
precision-tracking backtracker'ı) yalnızca call/exit'i ele alıyordu; diğer tüm
conditional'larda precision mask'leri olduğu gibi kalıyordu. Yani r6 r9'a bağlı olsa
bile sadece r6 precise işaretlendiyse, r9 hiçbir zaman precise işaretlenmiyordu. Bu
taint'in eksik olması verifier'ın iki state'i eşdeğer sayıp prune etmesine yol açar —
runtime'da aslında alınan güvensiz path'i atlar.
Commit'in alıntıladığı örnek state'ler: eski R6_rwD=Pscalar() R9_rwD=0 vs yeni
R6_w=scalar(umax=...) R9_w=-2147483648. r9 farklıdır (0 vs 0x80000000) ama precise
flag'i olmadığından sayılmaz, dolayısıyla güvenli kabul edilen pruning yanlıştır. Runtime'da
r6=0x400, r9=0x80000000 olur ve bir OOB map access üretir.
Walkthrough¶
PoC'nin sonu, verifier'ın in-bounds sandığı bir OOB read+write yapar:
21: (77) r6 >>= 10
22: (27) r6 *= 8192
23: (bf) r1 = r0
24: (0f) r0 += r6 ; verifier thinks r6==0; runtime large -> OOB
25: (79) r3 = *(u64 *)(r0 +0) ; OOB read
26: (7b) *(u64 *)(r1 +0) = r3 ; write back into map_value
27: (95) exit
NVD'ye göre bu, "güvensiz code path'lerin yanlışlıkla safe işaretlenmesi, bunun sonucunda
kernel memory'sinde arbitrary read/write, lateral privilege escalation ve container escape"
ile sonuçlanır. CAP_BPF veya CAP_SYS_ADMIN gerektirir.
Warning
Fix commit 71b547f56124 ("Fix incorrect verifier pruning due to missing register
precision taints", Daniel Borkmann), Fixes: b5dc0163d8fd. 5.4'ten 6.2 serisine kadarki
sürümleri etkiledi; 6.3 mainline (fix'in landed olduğu release) etkilenmez. Stable
backport'lar: 5.4.242 / 5.10.179 / 5.15.109 / 6.1.26 / 6.2.13 (6.3'te fix mainline'da
bulunduğundan ayrı bir backport gerekmez).
Fix, hem sreg'i hem dreg'i reg_mask'e OR'layan bir BPF_SRC == BPF_X branch'i ekler.
(Not: bu CVE find_equal_scalars/sync_linked_regs içinde değildir.)
Mitigation¶
sysctl kernel.unprivileged_bpf_disabled=1 ve unprivileged context'lerden CAP_BPF'i
düşürmek; fix precision propagation'ı geri getirir, böylece güvensiz path artık prune
edilmez ve program reddedilir ("math between map_value pointer and register with unbounded
min value is not allowed").