eBPF verifier register-limit vulnerability (CVE-2024-41003)¶
Bir register-vs-const karşılaştırmasının iki branch'i aynı geçici "fake" register'ı paylaşıyordu; bu yüzden bir branch'in bounds'unu güncellemek diğerini bozuyordu — geçersiz bir min>max state'i ve bir arbitrary kernel R/W primitive'i üretiyordu.
Mechanism¶
Note
kernel/bpf/verifier.c içindeki reg_set_min_max() bir constant'a karşı karşılaştırmayı
ele alırken geçici bir fake register kurar. False-branch ve true-branch register-2
pointer'ları (false_reg2, true_reg2) aynı fake register'ı gösteriyordu; bu yüzden
bir branch'in bounds'unu güncellemek diğerininkini bozuyordu. Sonuç min > max olan
geçersiz bir register state'idir (bir "REG INVARIANTS VIOLATION", örn. verifier
R6_w=0 ile biterken runtime değeri 1'dir). CAP_BPF ile bu, bir arbitrary kernel
memory read/write primitive'i ve local privilege escalation verir.
Bug, Google'ın Buzzer BPF fuzzer'ı ile bulundu (2024-06-07'de raporlandı, 2024-06-13'te düzeltildi). CVSS 7.8, CWE-787 (out-of-bounds write).
Walkthrough¶
Fix her branch'e fake register'ın kendi kopyasını verir, onu stack'ten verifier env'ine taşır:
/* include/linux/bpf_verifier.h: struct bpf_reg_state fake_reg[2]; */
memcpy(&env->fake_reg[1], &env->fake_reg[0], sizeof(env->fake_reg[0]));
/* pass &env->fake_reg[0] and &env->fake_reg[1] instead of one shared pointer */
Bir program, iki branch'ini verifier'ın çapraz-bozduğu bir register-vs-const karşılaştırması hazırlar; track edilen bounds'u runtime'la uyuşmayan geçersiz bir scalar ile biter — bu OOB primitive'i (daha geniş verifier-abuse pattern'inde olduğu gibi) kernel memory'sini read/write etmek ve privilege escalation için kullanılır.
Warning
Fix commit 41e8ab428a99 ("bpf: Fix reg_set_min_max corruption of fake_reg", Daniel
Borkmann), Fixes: 67420501e868 ("generalize reg_set_min_max() to handle non-const register
comparisons"). Linux 6.8'den 6.9.6'ya kadarki sürümleri etkiledi; 6.9.7'de düzeltildi.
Mitigation¶
sysctl kernel.unprivileged_bpf_disabled=1 ve CAP_BPF'i düşürmek; fix iki branch'in fake
register'larını izole eder, böylece hiçbiri diğerini bozmaz.