diff options
| author | Alexei Starovoitov <ast@kernel.org> | 2026-11-02 05:59:10 +0000 |
|---|---|---|
| committer | Alexei Starovoitov <ast@kernel.org> | 2026-11-02 17:53:14 +0000 |
| commit | 6185d4fc6e64439cad415d9bf527f8ffb3fa3db4 (patch) | |
| tree | 56271d2e67046ce18b84969402597347d7b4ccd8 /scripts/basic/split-include.c | |
| parent | 03b013897454064e0a2d84a8ba9a24753eb02f2b (diff) | |
| download | linux-6185d4fc6e64439cad415d9bf527f8ffb3fa3db4.tar.gz linux-6185d4fc6e64439cad415d9bf527f8ffb3fa3db4.zip | |
bpf: Fix the join of fp+0 with a value that is not a pointer to stack
arg_track follows pointers to the stack through registers and spills.
Scalar evolution and the removal of dead slots rely on it to know which
slots an insn reads and writes.
Where two paths meet, a register can be fp-N on one path and not a pointer
to the stack on the other path. There is no value for that. The join adds
a fake second offset, fp+0: with two offsets no store through the register
is a certain write. But for fp+0 the fake offset is the offset itself:
join(fp-8, none) = {fp-8, fp+0} two offsets
join(fp+0, none) = {fp+0} one offset: "exactly fp+0"
Then a store counts as a certain write to the stack, but at run time it can
go to other memory:
r7 = r10, or r7 = map_value + 8 ; arg_track: exactly fp+0
*(u64 *)(r10 - 8) = fp-24
*(u64 *)(r7 - 8) = map_value ; arg_track: fp-8 is overwritten
r8 = *(u64 *)(r10 - 8) ; fp-24 or map_value. arg_track: none
loop:
r1 = *(u64 *)(r10 - 24) ; the counter of the loop
...
*(u64 *)(r8 + 0) = 4096 ; arg_track: not a write to fp-24
Scalar evolution does not see the last store. It gives the counter the
range of a loop that only increments it. The prog loads, and it accesses
a map value out of bounds.
Valid progs are rejected as well. The store through r7 makes fp-8 dead, and
a later read of fp-8 fails with "slot poisoned by dead code elimination".
When the single offset is 0, drop the offsets. The result is a pointer to
an unknown slot of the frame, and all updates through it are weak.
Veristat sees no difference in selftests, Cilium and sched_ext.
Fixes: bf0c571f7feb ("bpf: introduce forward arg-tracking dataflow analysis")
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Link: https://patch.msgid.link/20261102055913.3598414-2-alexei.starovoitov@gmail.com
Diffstat (limited to 'scripts/basic/split-include.c')
0 files changed, 0 insertions, 0 deletions
