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