On Tue, Dec 19, 2023 at 5:51 AM Menglong Dong menglong8.dong@gmail.com wrote:
Add testcase for the logic that the verifier tracks the BPF_JNE for regs. The assembly function "reg_not_equal_const()" and "reg_equal_const" that we add is exactly converted from the following case:
u32 a = bpf_get_prandom_u32(); u64 b = 0;
a %= 8; /* the "a > 0" here will be optimized to "a != 0" */ if (a > 0) { /* now the range of a should be [1, 7] */ bpf_skb_store_bytes(skb, 0, &b, a, 0); }
Signed-off-by: Menglong Dong menglong8.dong@gmail.com
v5:
- add some comments to the function that we add
- add reg_not_equal_const()
.../selftests/bpf/progs/verifier_bounds.c | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+)
LGTM
Acked-by: Andrii Nakryiko andrii@kernel.org
diff --git a/tools/testing/selftests/bpf/progs/verifier_bounds.c b/tools/testing/selftests/bpf/progs/verifier_bounds.c index ec430b71730b..960998f16306 100644 --- a/tools/testing/selftests/bpf/progs/verifier_bounds.c +++ b/tools/testing/selftests/bpf/progs/verifier_bounds.c @@ -1075,4 +1075,66 @@ l0_%=: r0 = 0; \ : __clobber_all); }
+SEC("tc") +__description("bounds check with JMP_NE for reg edge") +__success __retval(0) +__naked void reg_not_equal_const(void) +{
asm volatile (" \
r6 = r1; \
r1 = 0; \
*(u64*)(r10 - 8) = r1; \
call %[bpf_get_prandom_u32]; \
r4 = r0; \
r4 &= 7; \
if r4 != 0 goto l0_%=; \
r0 = 0; \
exit; \
+l0_%=: r1 = r6; \
r2 = 0; \
r3 = r10; \
r3 += -8; \
r5 = 0; \
/* The 4th argument of bpf_skb_store_bytes is defined as \
* ARG_CONST_SIZE, so 0 is not allowed. The 'r4 != 0' \
* is providing us this exclusion of zero from initial \
* [0, 7] range. \
*/ \
call %[bpf_skb_store_bytes]; \
r0 = 0; \
exit; \
+" :
: __imm(bpf_get_prandom_u32),
__imm(bpf_skb_store_bytes)
: __clobber_all);
+}
+SEC("tc") +__description("bounds check with JMP_EQ for reg edge") +__success __retval(0) +__naked void reg_equal_const(void) +{
asm volatile (" \
r6 = r1; \
r1 = 0; \
*(u64*)(r10 - 8) = r1; \
call %[bpf_get_prandom_u32]; \
r4 = r0; \
r4 &= 7; \
if r4 == 0 goto l0_%=; \
r1 = r6; \
r2 = 0; \
r3 = r10; \
r3 += -8; \
r5 = 0; \
/* Just the same as what we do in reg_not_equal_const() */ \
call %[bpf_skb_store_bytes]; \
+l0_%=: r0 = 0; \
exit; \
+" :
: __imm(bpf_get_prandom_u32),
__imm(bpf_skb_store_bytes)
: __clobber_all);
+}
char _license[] SEC("license") = "GPL";
2.39.2