From: Paul Chaignon Thanks to the previous patch, if the tnum and u64 don't intersect on a branch, we can deduce the branch is dead code. This patch adds a verifier selftest for that case, with an invalid r10 write on the dead branch. Without the previous patch, this selftest fails as follows: 0: call bpf_get_prandom_u32#7 ; R0=scalar() 1: r6 = r0 ; R0=scalar(id=1) R6=scalar(id=1) 2: r1 = 0xe00000002 ; R1=0xe00000002 4: r2 = 0xf00000000 ; R2=0xf00000000 6: if r6 s< r1 goto pc+2 ; R1=0xe00000002 R6=scalar(id=1,smin=umin=0xe00000002,umax=0x7fffffffffffffff,var_off=(0x0; 0x7fffffffffffffff)) 7: if r6 s> r2 goto pc+1 ; R2=0xf00000000 R6=scalar(id=1,smin=umin=0xe00000002,smax=umax=0xf00000000,var_off=(0xe00000000; 0x1ffffffff)) 8: if w6 == 0x1 goto pc+1 ; R6=scalar(id=1,smin=umin=0xe00000002,smax=umax=0xf00000000,var_off=(0xe00000000; 0x1ffffffff)) 9: exit from 8 to 10: R0=scalar(id=1,smin=umin=0xe00000002,smax=umax=0xf00000000,smin32=umin32=1,smax32=umax32=1,var_off=(0xe00000001; 0x100000000)) R1=0xe00000002 R2=0xf00000000 R6=scalar(id=1,smin=umin=0xe00000002,smax=umax=0xf00000000,smin32=umin32=1,smax32=umax32=1,var_off=(0xe00000001; 0x100000000)) R10=fp0 10: R0=scalar(id=1,smin=umin=0xe00000002,smax=umax=0xf00000000,smin32=umin32=1,smax32=umax32=1,var_off=(0xe00000001; 0x100000000)) R1=0xe00000002 R2=0xf00000000 R6=scalar(id=1,smin=umin=0xe00000002,smax=umax=0xf00000000,smin32=umin32=1,smax32=umax32=1,var_off=(0xe00000001; 0x100000000)) R10=fp0 10: (b7) r10 = 0 frame pointer is read only Signed-off-by: Paul Chaignon --- .../selftests/bpf/progs/verifier_bounds.c | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/tools/testing/selftests/bpf/progs/verifier_bounds.c b/tools/testing/selftests/bpf/progs/verifier_bounds.c index c1ae013dee29..151c7a479a6b 100644 --- a/tools/testing/selftests/bpf/progs/verifier_bounds.c +++ b/tools/testing/selftests/bpf/progs/verifier_bounds.c @@ -2184,4 +2184,29 @@ __naked void tnums_equal_impossible_constant(void *ctx) : __clobber_all); } +SEC("socket") +__description("dead branch: tnum and u64 don't intersect on true branch") +__success +__naked void empty_tnum_u64_intersection(void *ctx) +{ + asm volatile(" \ + call %[bpf_get_prandom_u32]; \ + r6 = r0; \ + r1 = 0xe00000002 ll; \ + r2 = 0xf00000000 ll; \ + if r6 s< r1 goto +2; \ + /* On fallthrough, r6's u64=[0xe00000002;0xf00000000] */ \ + /* tnum=(0xe00000000; 0x1ffffffff) */ \ + if r6 s> r2 goto +1; \ + /* On fallthrough, r6's tnum=(0xe00000001; 0x100000000) */ \ + /* It doesn't intersect with the u64 so the condition is always false */ \ + if w6 == 1 goto +1; \ + exit; \ + r10 = 0; \ + exit; \ +" : + : __imm(bpf_get_prandom_u32) + : __clobber_all); +} + char _license[] SEC("license") = "GPL"; -- 2.51.0