]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
selftests/bpf: add testcase to verifier_bounds.c for BPF_JNE
authorMenglong Dong <menglong8.dong@gmail.com>
Tue, 19 Dec 2023 13:48:00 +0000 (21:48 +0800)
committerAlexei Starovoitov <ast@kernel.org>
Wed, 20 Dec 2023 01:18:56 +0000 (17:18 -0800)
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>
Acked-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/r/20231219134800.1550388-5-menglong8.dong@gmail.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
tools/testing/selftests/bpf/progs/verifier_bounds.c

index ec430b71730b0cd635f8d9b137768559713da708..960998f163063596a09ba49144109ac7e462328a 100644 (file)
@@ -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";