Skip to content

Commit

Permalink
selftests/bpf: adjust dummy_st_ops_success to detect additional error
Browse files Browse the repository at this point in the history
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 <[email protected]>
Signed-off-by: Eduard Zingerman <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Alexei Starovoitov <[email protected]>
  • Loading branch information
eddyz87 authored and Alexei Starovoitov committed Apr 25, 2024
1 parent 1479eaf commit 3b3b84a
Showing 1 changed file with 11 additions and 2 deletions.
13 changes: 11 additions & 2 deletions tools/testing/selftests/bpf/progs/dummy_st_ops_success.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down

0 comments on commit 3b3b84a

Please sign in to comment.