Skip to content

Commit d68cf53

Browse files
Docs: the walk VM's per-CPU state, and the matrix result it closed
1 parent 25b1218 commit d68cf53

2 files changed

Lines changed: 23 additions & 15 deletions

File tree

‎.github/workflows/kernel-matrix.yml‎

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,12 @@ name: kernel-matrix
3232
# generated from the runner's own BTF by `make bpf`. So the gating lines are
3333
# the LTS and stable kernels from 6.6 up. bpf-next is run but does not gate:
3434
# it is a moving target, and what it shows tends to arrive in stable soon
35-
# after — the walk VM's three nested bpf_loops verify in 14k instructions on
36-
# 6.12 and 6.18, but 7.2.7 backported a batch of verifier precision fixes
35+
# after. Case in point: the walk VM's three nested bpf_loops verified in 14k
36+
# instructions until 7.2.7 backported a batch of verifier precision fixes
3737
# for bpf_loop callbacks ("backtracking shouldn't clear outer frame R1-R5
38-
# for callbacks" and kin), after which the same object costs 850k in `step`
39-
# alone and hits the 1M limit on 7.2.8 and on bpf-next. 7.2.6 still loads
40-
# it. That 7.2 row is a real rejection on a stable kernel, so it gates.
38+
# for callbacks" and kin), after which the same object cost 850k in `step`
39+
# alone and hit the 1M limit on 7.2.8 and on bpf-next. Its state now lives
40+
# in a per-CPU map the verifier does not track, and it verifies in under 5k.
4141

4242
on:
4343
workflow_dispatch:

‎README.md‎

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -393,10 +393,18 @@ query overrides with `(kind)`. This is what tcpwalk2 does with a
393393
54 KB schema table rendered at build time from one kernel's BTF — a
394394
table that, checked here, had `snd_cwnd` forty bytes from where this
395395
kernel keeps it. The kernel side is derived from tcpwalk2's VM with
396-
one structural change: every op runs as a `bpf_loop` step, so the
396+
two structural changes. Every op runs as a `bpf_loop` step, so the
397397
verifier walks the dispatch once per call site instead of once per
398-
slot per section per field, which on this kernel was the difference
399-
between a million-instruction rejection and a load.
398+
slot per section per field. And the VM's mutable state lives in a
399+
one-element per-CPU array, not on the stack, with the callbacks
400+
reaching it by lookup and only the event pointer riding on the stack as
401+
the callback context: a callback loop is verified once only when its
402+
entry state converges with an earlier one, and the verifier does not
403+
track map memory, so nothing the ops do can tell one iteration from the
404+
last. With the state on the stack, the 7.2.7 verifier backports left
405+
the object simulating every one of its 8 × 16 × 8 nested iterations and
406+
hitting the million-instruction limit; with it in the map, the whole
407+
object verifies in under 5k instructions on every kernel in the matrix.
400408

401409
The event carries the socket's 4-tuple, state and the segment's
402410
sequence number and lengths, read through CO-RE in a fixed prologue,
@@ -478,13 +486,13 @@ buffer held before — a response head where curl's body should be.
478486
run also caught the 6.6 verifier rejecting the wire tap's
479487
`bpf_skb_load_bytes` size as possibly zero, since a verifier before
480488
6.9 does not narrow a register on a `!= 0` branch; the bound is now
481-
rebuilt by arithmetic. bpf-next runs but does not gate. The open
482-
finding is the walk VM: its three nested `bpf_loop`s verify in 14k
483-
instructions on 6.12 and 6.18 and on this host's 7.2.6, but stable
484-
7.2.7 backported a batch of verifier precision fixes for `bpf_loop`
485-
callbacks, after which `step` alone costs 850k and the object hits the
486-
one-million limit on 7.2.8 and on bpf-next. That row gates, because a
487-
stable kernel rejecting it is the matrix's job to say. `make veristat-matrix` runs the same thing
489+
rebuilt by arithmetic. The second catch was the walk VM: on this
490+
host's 7.2.6 it verified in 14k instructions, but stable 7.2.7
491+
backported a batch of verifier precision fixes for `bpf_loop`
492+
callbacks, after which the lvh 7.2.8 image and bpf-next ran it to the
493+
one-million limit. Moving the VM's state into a per-CPU map (see the
494+
walk VM section) brought it to under 5k everywhere. bpf-next runs but
495+
does not gate. `make veristat-matrix` runs the same thing
488496
locally with lvh + a static qemu (Linux, KVM, root for the VM), and
489497
`make veristat` is the single-kernel check against this host.
490498

0 commit comments

Comments
 (0)