freenode
Kernel & Low-Level

BPF verifier patches close gotox DoS and register-leak paths

Indirect-jump handling could stall loading for hours and, on a CFG mismatch, leave callee-saved registers under BPF control.

Daniel Borkmann has posted fixes for several serious flaws in how the BPF verifier handles indirect jumps (gotox), introduced when that feature landed for x86.

The worst correctness bug was a split between control-flow construction and jump resolution. Jump tables built for the CFG attributed maps by first entry, while the verifier resolved targets from whatever insn_array map the gotox register actually pointed at, without tying them back to the instruction's subprogram. A program could therefore jump into a subprogram the CFG never walked. On x86 the mismatched epilogue restored the wrong callee-saved set and left rbx, r13, r14, and r15 holding values the BPF program chose, exposing them to the kernel. James Burton and Nuoqi Gui reported that path. The fix confines resolved targets to the gotox's subprogram and requires each to appear in the successor set the CFG already walked.

Separately, STAR Labs SG reported load-time denial-of-service. Strongly connected component analysis rescanned a gotox's successors from index zero on every descent, turning a jump table of size k into O(k²) work; with k allowed up to the million-instruction complexity limit, a CPU could sit in that loop for a long time before verification started. Edge counts were also effectively unbounded: each gotox copied its subprogram's full table, so edges scaled as gotox count times distinct targets. Programs shaped so gotox instructions were themselves targets produced roughly a million edges and multi-second loads; similar shapes with large maps could take minutes to reject and extrapolated to tens of hours at the instruction limit.

The series records resume positions so the DFS is linear in edges, builds each subprogram jump table once instead of once per gotox, and caps total indirect-jump edges across the program at the existing instruction complexity limit. Selftests cover the edge cap and cross-subprogram corner cases. Ordinary switch-like programs sit far below the new bound.