mirror_ubuntu-kernels/tools/testing/selftests/bpf/verifier
John Fastabend e3effcdfe0 bpf, selftests: Verifier bounds tests need to be updated
After previous fix for zero extension test_verifier tests #65 and #66 now
fail. Before the fix we can see the alu32 mov op at insn 10

10: R0_w=map_value(id=0,off=0,ks=8,vs=8,imm=0)
    R1_w=invP(id=0,
              smin_value=4294967168,smax_value=4294967423,
              umin_value=4294967168,umax_value=4294967423,
              var_off=(0x0; 0x1ffffffff),
              s32_min_value=-2147483648,s32_max_value=2147483647,
              u32_min_value=0,u32_max_value=-1)
    R10=fp0 fp-8_w=mmmmmmmm
10: (bc) w1 = w1
11: R0_w=map_value(id=0,off=0,ks=8,vs=8,imm=0)
    R1_w=invP(id=0,
              smin_value=0,smax_value=2147483647,
              umin_value=0,umax_value=4294967295,
              var_off=(0x0; 0xffffffff),
              s32_min_value=-2147483648,s32_max_value=2147483647,
              u32_min_value=0,u32_max_value=-1)
    R10=fp0 fp-8_w=mmmmmmmm

After the fix at insn 10 because we have 's32_min_value < 0' the following
step 11 now has 'smax_value=U32_MAX' where before we pulled the s32_max_value
bound into the smax_value as seen above in 11 with smax_value=2147483647.

10: R0_w=map_value(id=0,off=0,ks=8,vs=8,imm=0)
    R1_w=inv(id=0,
             smin_value=4294967168,smax_value=4294967423,
             umin_value=4294967168,umax_value=4294967423,
             var_off=(0x0; 0x1ffffffff),
             s32_min_value=-2147483648, s32_max_value=2147483647,
             u32_min_value=0,u32_max_value=-1)
    R10=fp0 fp-8_w=mmmmmmmm
10: (bc) w1 = w1
11: R0_w=map_value(id=0,off=0,ks=8,vs=8,imm=0)
    R1_w=inv(id=0,
             smin_value=0,smax_value=4294967295,
             umin_value=0,umax_value=4294967295,
             var_off=(0x0; 0xffffffff),
             s32_min_value=-2147483648, s32_max_value=2147483647,
             u32_min_value=0, u32_max_value=-1)
    R10=fp0 fp-8_w=mmmmmmmm

The fall out of this is by the time we get to the failing instruction at
step 14 where previously we had the following:

14: R0_w=map_value(id=0,off=0,ks=8,vs=8,imm=0)
    R1_w=inv(id=0,
             smin_value=72057594021150720,smax_value=72057594029539328,
             umin_value=72057594021150720,umax_value=72057594029539328,
             var_off=(0xffffffff000000; 0xffffff),
             s32_min_value=-16777216,s32_max_value=-1,
             u32_min_value=-16777216,u32_max_value=-1)
    R10=fp0 fp-8_w=mmmmmmmm
14: (0f) r0 += r1

We now have,

14: R0_w=map_value(id=0,off=0,ks=8,vs=8,imm=0)
    R1_w=inv(id=0,
             smin_value=0,smax_value=72057594037927935,
             umin_value=0,umax_value=72057594037927935,
             var_off=(0x0; 0xffffffffffffff),
             s32_min_value=-2147483648,s32_max_value=2147483647,
             u32_min_value=0,u32_max_value=-1)
    R10=fp0 fp-8_w=mmmmmmmm
14: (0f) r0 += r1

In the original step 14 'smin_value=72057594021150720' this trips the logic
in the verifier function check_reg_sane_offset(),

 if (smin >= BPF_MAX_VAR_OFF || smin <= -BPF_MAX_VAR_OFF) {
	verbose(env, "value %lld makes %s pointer be out of bounds\n",
		smin, reg_type_str[type]);
	return false;
 }

Specifically, the 'smin <= -BPF_MAX_VAR_OFF' check. But with the fix
at step 14 we have bounds 'smin_value=0' so the above check is not tripped
because BPF_MAX_VAR_OFF=1<<29.

We have a smin_value=0 here because at step 10 the smaller smin_value=0 means
the subtractions at steps 11 and 12 bring the smin_value negative.

11: (17) r1 -= 2147483584
12: (17) r1 -= 2147483584
13: (77) r1 >>= 8

Then the shift clears the top bit and smin_value is set to 0. Note we still
have the smax_value in the fixed code so any reads will fail. An alternative
would be to have reg_sane_check() do both smin and smax value tests.

To fix the test we can omit the 'r1 >>=8' at line 13. This will change the
err string, but keeps the intention of the test as suggseted by the title,
"check after truncation of boundary-crossing range". If the verifier logic
changes a different value is likely to be thrown in the error or the error
will no longer be thrown forcing this test to be examined. With this change
we see the new state at step 13.

13: R0_w=map_value(id=0,off=0,ks=8,vs=8,imm=0)
    R1_w=invP(id=0,
              smin_value=-4294967168,smax_value=127,
              umin_value=0,umax_value=18446744073709551615,
              s32_min_value=-2147483648,s32_max_value=2147483647,
              u32_min_value=0,u32_max_value=-1)
    R10=fp0 fp-8_w=mmmmmmmm

Giving the expected out of bounds error, "value -4294967168 makes map_value
pointer be out of bounds" However, for unpriv case we see a different error
now because of the mixed signed bounds pointer arithmatic. This seems OK so
I've only added the unpriv_errstr for this. Another optino may have been to
do addition on r1 instead of subtraction but I favor the approach above
slightly.

Signed-off-by: John Fastabend <john.fastabend@gmail.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Acked-by: Yonghong Song <yhs@fb.com>
Link: https://lore.kernel.org/bpf/159077333942.6014.14004320043595756079.stgit@john-Precision-5820-Tower
2020-05-29 13:34:06 -07:00
..
.gitignore .gitignore: add SPDX License Identifier 2020-03-25 11:50:48 +01:00
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, selftests: Verifier bounds tests need to be updated 2020-05-29 13:34:06 -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 test for JMP32 JSET BPF_X with upper bits set 2020-03-06 14:17:39 +01: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 bpf, selftests: Add test for BPF_STX BPF_B storing R10 2020-04-20 19:25:30 -07:00
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 bpf: Forbid XADD on spilled pointers for unprivileged users 2020-04-20 18:41:34 -07:00
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