]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
bpf: Test nospec after dead stack write in helper
authorLuis Gerhorst <luis.gerhorst@fau.de>
Tue, 27 Jan 2026 11:59:12 +0000 (12:59 +0100)
committerAlexei Starovoitov <ast@kernel.org>
Thu, 29 Jan 2026 02:41:57 +0000 (18:41 -0800)
Without the fix from the previous commit, the selftest fails:

$ ./tools/testing/selftests/bpf/vmtest.sh -- \
        ./test_progs -t verifier_unpriv
[...]
run_subtest:PASS:obj_open_mem 0 nsec
libbpf: BTF loading error: -EPERM
libbpf: Error loading .BTF into kernel: -EPERM. BTF is optional, ignoring.
libbpf: prog 'unpriv_nospec_after_helper_stack_write': BPF program load failed: -EFAULT
libbpf: prog 'unpriv_nospec_after_helper_stack_write': failed to load: -EFAULT
libbpf: failed to load object 'verifier_unpriv'
run_subtest:FAIL:unexpected_load_failure unexpected error: -14 (errno 14)
VERIFIER LOG:
=============
0: R1=ctx() R10=fp0
0: (b7) r0 = 0                        ; R0=P0
1: (55) if r0 != 0x1 goto pc+6 2: R0=Pscalar() R1=ctx() R10=fp0
2: (b7) r2 = 0                        ; R2=P0
3: (bf) r3 = r10                      ; R3=fp0 R10=fp0
4: (07) r3 += -16                     ; R3=fp-16
5: (b7) r4 = 4                        ; R4=P4
6: (b7) r5 = 0                        ; R5=P0
7: (85) call bpf_skb_load_bytes_relative#68
verifier bug: speculation barrier after jump instruction may not have the desired effect (BPF_CLASS(insn->code) == BPF_JMP || BPF_CLASS(insn->code) == BPF_JMP32)
processed 9 insns (limit 1000000) max_states_per_insn 0 total_states 0 peak_states 0 mark_read 0
=============
[...]

The test is based on the PoC from the report.

Signed-off-by: Luis Gerhorst <luis.gerhorst@fau.de>
Reported-by: Yinhao Hu <dddddd@hust.edu.cn>
Reported-by: Kaiyan Mei <M202472210@hust.edu.cn>
Reported-by: Dongliang Mu <dzm91@hust.edu.cn>
Link: https://lore.kernel.org/bpf/7678017d-b760-4053-a2d8-a6879b0dbeeb@hust.edu.cn/
Link: https://lore.kernel.org/r/20260127115912.3026761-3-luis.gerhorst@fau.de
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
tools/testing/selftests/bpf/progs/verifier_unpriv.c

index 28b4f7035cebd1d14050f377bc04eb5d83a58411..8ee1243e62a827ec4cf810a47d6f3e4f94926716 100644 (file)
@@ -950,4 +950,26 @@ l3_%=:     r0 = 0;                                         \
 "      ::: __clobber_all);
 }
 
+SEC("socket")
+__description("unpriv: nospec after dead stack write in helper")
+__success __success_unpriv
+__retval(0)
+/* Dead code sanitizer rewrites the call to `goto -1`. */
+__naked void unpriv_dead_helper_stack_write_nospec_result(void)
+{
+       asm volatile ("                                 \
+       r0 = 0;                                         \
+       if r0 != 1 goto l0_%=;                          \
+       r2 = 0;                                         \
+       r3 = r10;                                       \
+       r3 += -16;                                      \
+       r4 = 4;                                         \
+       r5 = 0;                                         \
+       call %[bpf_skb_load_bytes_relative];            \
+l0_%=: exit;                                           \
+"      :
+       : __imm(bpf_skb_load_bytes_relative)
+       : __clobber_all);
+}
+
 char _license[] SEC("license") = "GPL";