linux/tools/testing/selftests/bpf/verifier
John Fastabend 9ac26e9973 bpf: Test_verifier, bpf_get_stack return value add <0
With current ALU32 subreg handling and retval refine fix from last
patches we see an expected failure in test_verifier. With verbose
verifier state being printed at each step for clarity we have the
following relavent lines [I omit register states that are not
necessarily useful to see failure cause],

#101/p bpf_get_stack return R0 within range FAIL
Failed to load prog 'Success'!
[..]
14: (85) call bpf_get_stack#67
 R0_w=map_value(id=0,off=0,ks=8,vs=48,imm=0)
 R3_w=inv48
15:
 R0=inv(id=0,smax_value=48,var32_off=(0x0; 0xffffffff))
15: (b7) r1 = 0
16:
 R0=inv(id=0,smax_value=48,var32_off=(0x0; 0xffffffff))
 R1_w=inv0
16: (bf) r8 = r0
17:
 R0=inv(id=0,smax_value=48,var32_off=(0x0; 0xffffffff))
 R1_w=inv0
 R8_w=inv(id=0,smax_value=48,var32_off=(0x0; 0xffffffff))
17: (67) r8 <<= 32
18:
 R0=inv(id=0,smax_value=48,var32_off=(0x0; 0xffffffff))
 R1_w=inv0
 R8_w=inv(id=0,smax_value=9223372032559808512,
               umax_value=18446744069414584320,
               var_off=(0x0; 0xffffffff00000000),
               s32_min_value=0,
               s32_max_value=0,
               u32_max_value=0,
               var32_off=(0x0; 0x0))
18: (c7) r8 s>>= 32
19
 R0=inv(id=0,smax_value=48,var32_off=(0x0; 0xffffffff))
 R1_w=inv0
 R8_w=inv(id=0,smin_value=-2147483648,
               smax_value=2147483647,
               var32_off=(0x0; 0xffffffff))
19: (cd) if r1 s< r8 goto pc+16
 R0=inv(id=0,smax_value=48,var32_off=(0x0; 0xffffffff))
 R1_w=inv0
 R8_w=inv(id=0,smin_value=-2147483648,
               smax_value=0,
               var32_off=(0x0; 0xffffffff))
20:
 R0=inv(id=0,smax_value=48,var32_off=(0x0; 0xffffffff))
 R1_w=inv0
 R8_w=inv(id=0,smin_value=-2147483648,
               smax_value=0,
 R9=inv48
20: (1f) r9 -= r8
21: (bf) r2 = r7
22:
 R2_w=map_value(id=0,off=0,ks=8,vs=48,imm=0)
22: (0f) r2 += r8
value -2147483648 makes map_value pointer be out of bounds

After call bpf_get_stack() on line 14 and some moves we have at line 16
an r8 bound with max_value 48 but an unknown min value. This is to be
expected bpf_get_stack call can only return a max of the input size but
is free to return any negative error in the 32-bit register space. The
C helper is returning an int so will use lower 32-bits.

Lines 17 and 18 clear the top 32 bits with a left/right shift but use
ARSH so we still have worst case min bound before line 19 of -2147483648.
At this point the signed check 'r1 s< r8' meant to protect the addition
on line 22 where dst reg is a map_value pointer may very well return
true with a large negative number. Then the final line 22 will detect
this as an invalid operation and fail the program. What we want to do
is proceed only if r8 is positive non-error. So change 'r1 s< r8' to
'r1 s> r8' so that we jump if r8 is negative.

Next we will throw an error because we access past the end of the map
value. The map value size is 48 and sizeof(struct test_val) is 48 so
we walk off the end of the map value on the second call to
get bpf_get_stack(). Fix this by changing sizeof(struct test_val) to
24 by using 'sizeof(struct test_val) / 2'. After this everything passes
as expected.

Signed-off-by: John Fastabend <john.fastabend@gmail.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Link: https://lore.kernel.org/bpf/158560426019.10843.3285429543232025187.stgit@john-Precision-5820-Tower
2020-03-30 15:00:30 -07:00
..
.gitignore
and.c
array_access.c selftests/bpf: fix "valid read map access into a read-only array 1" on s390 2019-07-18 13:49:21 -07:00
basic_call.c
basic_instr.c selftests: bpf: add tests for shifts by zero 2019-07-03 11:14:28 +02:00
basic_stack.c
basic_stx_ldx.c
basic.c
bounds_deduction.c selftests: bpf: break up the rest of test_verifier 2019-01-27 21:37:45 -08:00
bounds_mix_sign_unsign.c
bounds.c bpf: Test_verifier, #70 error message updates for 32-bit right shift 2020-03-25 23:05:54 -07:00
bpf_get_stack.c bpf: Test_verifier, bpf_get_stack return value add <0 2020-03-30 15:00:30 -07:00
calls.c selftests/bpf: fix tests 2019-06-19 02:22:52 +02:00
cfg.c selftests/bpf: fix tests 2019-06-19 02:22:52 +02:00
cgroup_inv_retcode.c selftests: bpf: break up the rest of test_verifier 2019-01-27 21:37:45 -08:00
cgroup_skb.c
cgroup_storage.c
const_or.c
ctx_sk_msg.c selftests/bpf: add "any alignment" annotation for some tests 2019-02-05 16:56:10 +01:00
ctx_skb.c selftests/bpf: Test new __sk_buff field gso_size 2020-03-03 16:23:59 -08:00
ctx.c bpf: Add selftest cases for ctx_or_null argument type 2020-03-27 19:40:39 -07:00
dead_code.c selftests: bpf: break up the rest of test_verifier 2019-01-27 21:37:45 -08:00
direct_packet_access.c selftests/bpf: fix tests due to const spill/fill 2019-06-19 02:22:51 +02:00
direct_stack_access_wraparound.c
direct_value_access.c bpf, selftest: test {rd, wr}only flags and direct value access 2019-04-09 17:05:47 -07:00
div0.c
div_overflow.c bpf: fix div64 overflow tests to properly detect errors 2019-06-13 23:07:00 +02:00
event_output.c selftests/bpf: Add selftests for bpf_perf_event_output 2019-07-25 17:56:00 -07:00
helper_access_var_len.c selftests/bpf: fix tests due to const spill/fill 2019-06-19 02:22:51 +02:00
helper_packet_access.c
helper_value_access.c
int_ptr.c selftests/bpf: Test ARG_PTR_TO_LONG arg type 2019-04-12 13:54:59 -07:00
jit.c bpf, x32: Fix bug for BPF_JMP | {BPF_JSGT, BPF_JSLE, BPF_JSLT, BPF_JSGE} 2019-05-01 23:32:16 +02:00
jmp32.c selftests/bpf: Add verifier tests for better jmp32 register bounds 2019-11-24 16:58:46 -08:00
jset.c selftests/bpf: add "any alignment" annotation for some tests 2019-02-05 16:56:10 +01:00
jump.c bpf: add various test cases for backward jumps 2019-05-13 01:08:55 +02:00
junk_insn.c
ld_abs.c selftests: bpf: break up the rest of test_verifier 2019-01-27 21:37:45 -08:00
ld_dw.c selftests/bpf: synthetic tests to push verifier limits 2019-04-04 01:27:38 +02:00
ld_imm64.c bpf: fix replace_map_fd_with_map_ptr's ldimm64 second imm field 2019-03-07 08:47:13 -08:00
ld_ind.c
leak_ptr.c
loops1.c bpf: Add loop test case with 32 bit reg comparison against 0 2019-10-04 12:27:36 -07:00
lwt.c
map_in_map.c
map_ptr_mixing.c selftests: bpf: break up the rest of test_verifier 2019-01-27 21:37:45 -08:00
map_ret_val.c
masking.c selftests: bpf: break up the rest of test_verifier 2019-01-27 21:37:45 -08:00
meta_access.c selftests: bpf: break up the rest of test_verifier 2019-01-27 21:37:45 -08:00
perf_event_sample_period.c
precise.c selftests/bpf: precision tracking tests 2019-09-05 13:55:50 +02:00
prevent_map_lookup.c bpf: Allow bpf_map_lookup_elem() on an xskmap 2019-06-10 23:31:26 -07:00
raw_stack.c
raw_tp_writable.c selftests: bpf: test writable buffers in raw tps 2019-04-26 19:04:19 -07:00
ref_tracking.c bpf: Add further test_verifier cases for record_func_key 2019-12-19 13:39:22 -08:00
runtime_jit.c bpf: Add further test_verifier cases for record_func_key 2019-12-19 13:39:22 -08:00
scale.c selftests/bpf: two scale tests 2019-04-16 10:18:15 +02:00
search_pruning.c selftests: bpf: break up the rest of test_verifier 2019-01-27 21:37:45 -08:00
sock.c tools/bpf: Add bpf_map_lookup_elem selftest for xskmap 2019-06-10 23:31:26 -07:00
spill_fill.c selftests/bpf: add "any alignment" annotation for some tests 2019-02-05 16:56:10 +01:00
spin_lock.c selftests/bpf: add "any alignment" annotation for some tests 2019-02-05 16:56:10 +01:00
stack_ptr.c
subreg.c selftests: bpf: complete sub-register zero extension checks 2019-05-29 13:31:05 +02:00
uninit.c
unpriv.c selftests/bpf: allow specifying helper for BPF_SK_LOOKUP 2019-03-21 18:59:11 -07:00
value_adj_spill.c
value_illegal_alu.c
value_or_null.c
value_ptr_arith.c selftests/bpf: fix "alu with different scalars 1" on s390 2019-07-16 09:20:08 -07:00
value.c
var_off.c selftests/bpf: Test unbounded var_off stack access 2019-04-05 16:50:08 +02:00
wide_access.c selftests/bpf: add selftests for wide loads 2019-07-15 23:15:53 +02:00
xadd.c selftests: bpf: break up the rest of test_verifier 2019-01-27 21:37:45 -08:00
xdp_direct_packet_access.c selftests: bpf: break up the rest of test_verifier 2019-01-27 21:37:45 -08:00
xdp.c selftests: bpf: break up the rest of test_verifier 2019-01-27 21:37:45 -08:00