]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
selftests/bpf: adjust dummy_st_ops_success to detect additional error
authorEduard Zingerman <eddyz87@gmail.com>
Wed, 24 Apr 2024 01:28:18 +0000 (18:28 -0700)
committerAlexei Starovoitov <ast@kernel.org>
Thu, 25 Apr 2024 19:42:43 +0000 (12:42 -0700)
As reported by Jose E. Marchesi in off-list discussion, GCC and LLVM
generate slightly different code for dummy_st_ops_success/test_1():

  SEC("struct_ops/test_1")
  int BPF_PROG(test_1, struct bpf_dummy_ops_state *state)
  {
   int ret;

   if (!state)
   return 0xf2f3f4f5;

   ret = state->val;
   state->val = 0x5a;
   return ret;
  }

  GCC-generated                  LLVM-generated
  ----------------------------   ---------------------------
  0: r1 = *(u64 *)(r1 + 0x0)     0: w0 = -0xd0c0b0b
  1: if r1 == 0x0 goto 5f        1: r1 = *(u64 *)(r1 + 0x0)
  2: r0 = *(s32 *)(r1 + 0x0)     2: if r1 == 0x0 goto 6f
  3: *(u32 *)(r1 + 0x0) = 0x5a   3: r0 = *(u32 *)(r1 + 0x0)
  4: exit                        4: w2 = 0x5a
  5: r0 = -0xd0c0b0b             5: *(u32 *)(r1 + 0x0) = r2
  6: exit                        6: exit

If the 'state' argument is not marked as nullable in
net/bpf/bpf_dummy_struct_ops.c, the verifier would assume that
'r1 == 0x0' is never true:
- for the GCC version, this means that instructions #5-6 would be
  marked as dead and removed;
- for the LLVM version, all instructions would be marked as live.

The test dummy_st_ops/dummy_init_ret_value actually sets the 'state'
parameter to NULL.

Therefore, when the 'state' argument is not marked as nullable,
the GCC-generated version of the code would trigger a NULL pointer
dereference at instruction #3.

This patch updates the test_1() test case to always follow a shape
similar to the GCC-generated version above, in order to verify whether
the 'state' nullability is marked correctly.

Reported-by: Jose E. Marchesi <jemarch@gnu.org>
Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
Link: https://lore.kernel.org/r/20240424012821.595216-3-eddyz87@gmail.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
tools/testing/selftests/bpf/progs/dummy_st_ops_success.c

index 1efa746c25dc7767dfeb1d0ca6d9d28aa1ddabf9..cc7b69b001aaede0357f9b050554150aae889f76 100644 (file)
@@ -11,8 +11,17 @@ int BPF_PROG(test_1, struct bpf_dummy_ops_state *state)
 {
        int ret;
 
-       if (!state)
-               return 0xf2f3f4f5;
+       /* Check that 'state' nullable status is detected correctly.
+        * If 'state' argument would be assumed non-null by verifier
+        * the code below would be deleted as dead (which it shouldn't).
+        * Hide it from the compiler behind 'asm' block to avoid
+        * unnecessary optimizations.
+        */
+       asm volatile (
+               "if %[state] != 0 goto +2;"
+               "r0 = 0xf2f3f4f5;"
+               "exit;"
+       ::[state]"p"(state));
 
        ret = state->val;
        state->val = 0x5a;