Skip to content

eBPF verifier abuse

Find a bug where the verifier's tracked register bounds diverge from the real runtime value, then build OOB pointer arithmetic on a BPF map to obtain arbitrary kernel read/write.

Mechanism

Note

BPF verifier'ı, load'dan önce bir program'ın güvenli olduğunu statik olarak kanıtlar. Her register için scalar bounds takip eder — umin_value/umax_value, smin_value/smax_value, artı 32-bit variant'lar — ve bir tnum var_off ({mask, value}: mask'te set olan bit'ler unknown'dır). Loop/back-edge'leri ve pointer karşılaştırmalarını yasaklar, yalnızca pointer'lara eklenen scalar'lara izin verir ve pointer arithmetic'in bir map'in güvenli bounds'u içinde kalmasını gerektirir. Tüm verifier exploit sınıfı tek bir invariant kırılmasına iner: bir scalar'ın takip edilen bounds'unu gerçek runtime değeriyle uyuşmaz hâle getir (verifier R = 0 sanır, runtime R = 1), sonra o register'ı bir BPF map value/array pointer'ına karşı offset olarak kullan; böylece verifier erişimin in-bounds olduğuna inanırken o aslında out of bounds'tur.

Walkthrough

chompie1337'nin "Kernel Pwning with eBPF: a Love Story"'sindeki gibi generic primitive inşası:

  1. "0-ama-aslında-1" bir register elde etmek için verifier bug'ını tetikle.
  2. Onu bir map value/array üzerinde pointer arithmetic'te kullan -> map belleği üzerinde OOB read ve OOB write.
  3. Bir map value üzerinden bir kernel pointer leak'le, kernel base'ini hesapla.
  4. Bir hedefi overwrite et — klasik olarak cred struct'ı (uid 0 yap) ya da modprobe_path.

Altyapı: bpf() syscall'ı (BPF_MAP_CREATE, BPF_MAP_UPDATE_ELEM, BPF_MAP_LOOKUP_ELEM) ve map value'larına pointer elde etmek için map_lookup_elem helper'ı.

Warning

O blog'daki işlenmiş örnek, ayrı ZDI CVE-2020-8835 değil, CVE-2021-3490'dır (ALU32 bitwise bounds). Her belirli verifier bug'ı için özel kayıtlara bakın; bu not yeniden kullanılabilir istismar kalıbını kapsar.

Mitigation

sysctl kernel.unprivileged_bpf_disabled=1 (ya da BPF_UNPRIV_DEFAULT_OFF) unprivileged load'u bloklar. Constant blinding (net.core.bpf_jit_harden) ve read-only JIT page'leri post-exploitation adımını sertleştirir. Altta yatan her verifier bug'ı kernel/bpf/verifier.c içinde bounds-tracking düzeltmeleri olarak tek tek fix'lenir.

References