diff options
Diffstat (limited to 'tools/testing/selftests/bpf/progs/dynptr_fail.c')
| -rw-r--r-- | tools/testing/selftests/bpf/progs/dynptr_fail.c | 94 | 
1 files changed, 65 insertions, 29 deletions
diff --git a/tools/testing/selftests/bpf/progs/dynptr_fail.c b/tools/testing/selftests/bpf/progs/dynptr_fail.c index 0a26c243e6e9..b0f08ff024fb 100644 --- a/tools/testing/selftests/bpf/progs/dynptr_fail.c +++ b/tools/testing/selftests/bpf/progs/dynptr_fail.c @@ -65,7 +65,7 @@ static int get_map_val_dynptr(struct bpf_dynptr *ptr)  /* Every bpf_ringbuf_reserve_dynptr call must have a corresponding   * bpf_ringbuf_submit/discard_dynptr call   */ -SEC("?raw_tp/sys_nanosleep") +SEC("?raw_tp")  int ringbuf_missing_release1(void *ctx)  {  	struct bpf_dynptr ptr; @@ -77,7 +77,7 @@ int ringbuf_missing_release1(void *ctx)  	return 0;  } -SEC("?raw_tp/sys_nanosleep") +SEC("?raw_tp")  int ringbuf_missing_release2(void *ctx)  {  	struct bpf_dynptr ptr1, ptr2; @@ -112,7 +112,7 @@ static int missing_release_callback_fn(__u32 index, void *data)  }  /* Any dynptr initialized within a callback must have bpf_dynptr_put called */ -SEC("?raw_tp/sys_nanosleep") +SEC("?raw_tp")  int ringbuf_missing_release_callback(void *ctx)  {  	bpf_loop(10, missing_release_callback_fn, NULL, 0); @@ -120,7 +120,7 @@ int ringbuf_missing_release_callback(void *ctx)  }  /* Can't call bpf_ringbuf_submit/discard_dynptr on a non-initialized dynptr */ -SEC("?raw_tp/sys_nanosleep") +SEC("?raw_tp")  int ringbuf_release_uninit_dynptr(void *ctx)  {  	struct bpf_dynptr ptr; @@ -132,7 +132,7 @@ int ringbuf_release_uninit_dynptr(void *ctx)  }  /* A dynptr can't be used after it has been invalidated */ -SEC("?raw_tp/sys_nanosleep") +SEC("?raw_tp")  int use_after_invalid(void *ctx)  {  	struct bpf_dynptr ptr; @@ -151,7 +151,7 @@ int use_after_invalid(void *ctx)  }  /* Can't call non-dynptr ringbuf APIs on a dynptr ringbuf sample */ -SEC("?raw_tp/sys_nanosleep") +SEC("?raw_tp")  int ringbuf_invalid_api(void *ctx)  {  	struct bpf_dynptr ptr; @@ -173,7 +173,7 @@ done:  }  /* Can't add a dynptr to a map */ -SEC("?raw_tp/sys_nanosleep") +SEC("?raw_tp")  int add_dynptr_to_map1(void *ctx)  {  	struct bpf_dynptr ptr; @@ -190,7 +190,7 @@ int add_dynptr_to_map1(void *ctx)  }  /* Can't add a struct with an embedded dynptr to a map */ -SEC("?raw_tp/sys_nanosleep") +SEC("?raw_tp")  int add_dynptr_to_map2(void *ctx)  {  	struct test_info x; @@ -207,7 +207,7 @@ int add_dynptr_to_map2(void *ctx)  }  /* A data slice can't be accessed out of bounds */ -SEC("?raw_tp/sys_nanosleep") +SEC("?raw_tp")  int data_slice_out_of_bounds_ringbuf(void *ctx)  {  	struct bpf_dynptr ptr; @@ -227,7 +227,7 @@ done:  	return 0;  } -SEC("?raw_tp/sys_nanosleep") +SEC("?raw_tp")  int data_slice_out_of_bounds_map_value(void *ctx)  {  	__u32 key = 0, map_val; @@ -247,8 +247,8 @@ int data_slice_out_of_bounds_map_value(void *ctx)  }  /* A data slice can't be used after it has been released */ -SEC("?raw_tp/sys_nanosleep") -int data_slice_use_after_release(void *ctx) +SEC("?raw_tp") +int data_slice_use_after_release1(void *ctx)  {  	struct bpf_dynptr ptr;  	struct sample *sample; @@ -272,8 +272,44 @@ done:  	return 0;  } +/* A data slice can't be used after it has been released. + * + * This tests the case where the data slice tracks a dynptr (ptr2) + * that is at a non-zero offset from the frame pointer (ptr1 is at fp, + * ptr2 is at fp - 16). + */ +SEC("?raw_tp") +int data_slice_use_after_release2(void *ctx) +{ +	struct bpf_dynptr ptr1, ptr2; +	struct sample *sample; + +	bpf_ringbuf_reserve_dynptr(&ringbuf, 64, 0, &ptr1); +	bpf_ringbuf_reserve_dynptr(&ringbuf, sizeof(*sample), 0, &ptr2); + +	sample = bpf_dynptr_data(&ptr2, 0, sizeof(*sample)); +	if (!sample) +		goto done; + +	sample->pid = 23; + +	bpf_ringbuf_submit_dynptr(&ptr2, 0); + +	/* this should fail */ +	sample->pid = 23; + +	bpf_ringbuf_submit_dynptr(&ptr1, 0); + +	return 0; + +done: +	bpf_ringbuf_discard_dynptr(&ptr2, 0); +	bpf_ringbuf_discard_dynptr(&ptr1, 0); +	return 0; +} +  /* A data slice must be first checked for NULL */ -SEC("?raw_tp/sys_nanosleep") +SEC("?raw_tp")  int data_slice_missing_null_check1(void *ctx)  {  	struct bpf_dynptr ptr; @@ -293,7 +329,7 @@ int data_slice_missing_null_check1(void *ctx)  }  /* A data slice can't be dereferenced if it wasn't checked for null */ -SEC("?raw_tp/sys_nanosleep") +SEC("?raw_tp")  int data_slice_missing_null_check2(void *ctx)  {  	struct bpf_dynptr ptr; @@ -315,7 +351,7 @@ done:  /* Can't pass in a dynptr as an arg to a helper function that doesn't take in a   * dynptr argument   */ -SEC("?raw_tp/sys_nanosleep") +SEC("?raw_tp")  int invalid_helper1(void *ctx)  {  	struct bpf_dynptr ptr; @@ -329,7 +365,7 @@ int invalid_helper1(void *ctx)  }  /* A dynptr can't be passed into a helper function at a non-zero offset */ -SEC("?raw_tp/sys_nanosleep") +SEC("?raw_tp")  int invalid_helper2(void *ctx)  {  	struct bpf_dynptr ptr; @@ -344,7 +380,7 @@ int invalid_helper2(void *ctx)  }  /* A bpf_dynptr is invalidated if it's been written into */ -SEC("?raw_tp/sys_nanosleep") +SEC("?raw_tp")  int invalid_write1(void *ctx)  {  	struct bpf_dynptr ptr; @@ -365,7 +401,7 @@ int invalid_write1(void *ctx)   * A bpf_dynptr can't be used as a dynptr if it has been written into at a fixed   * offset   */ -SEC("?raw_tp/sys_nanosleep") +SEC("?raw_tp")  int invalid_write2(void *ctx)  {  	struct bpf_dynptr ptr; @@ -388,7 +424,7 @@ int invalid_write2(void *ctx)   * A bpf_dynptr can't be used as a dynptr if it has been written into at a   * non-const offset   */ -SEC("?raw_tp/sys_nanosleep") +SEC("?raw_tp")  int invalid_write3(void *ctx)  {  	struct bpf_dynptr ptr; @@ -419,7 +455,7 @@ static int invalid_write4_callback(__u32 index, void *data)  /* If the dynptr is written into in a callback function, it should   * be invalidated as a dynptr   */ -SEC("?raw_tp/sys_nanosleep") +SEC("?raw_tp")  int invalid_write4(void *ctx)  {  	struct bpf_dynptr ptr; @@ -436,7 +472,7 @@ int invalid_write4(void *ctx)  /* A globally-defined bpf_dynptr can't be used (it must reside as a stack frame) */  struct bpf_dynptr global_dynptr; -SEC("?raw_tp/sys_nanosleep") +SEC("?raw_tp")  int global(void *ctx)  {  	/* this should fail */ @@ -448,7 +484,7 @@ int global(void *ctx)  }  /* A direct read should fail */ -SEC("?raw_tp/sys_nanosleep") +SEC("?raw_tp")  int invalid_read1(void *ctx)  {  	struct bpf_dynptr ptr; @@ -464,7 +500,7 @@ int invalid_read1(void *ctx)  }  /* A direct read at an offset should fail */ -SEC("?raw_tp/sys_nanosleep") +SEC("?raw_tp")  int invalid_read2(void *ctx)  {  	struct bpf_dynptr ptr; @@ -479,7 +515,7 @@ int invalid_read2(void *ctx)  }  /* A direct read at an offset into the lower stack slot should fail */ -SEC("?raw_tp/sys_nanosleep") +SEC("?raw_tp")  int invalid_read3(void *ctx)  {  	struct bpf_dynptr ptr1, ptr2; @@ -505,7 +541,7 @@ static int invalid_read4_callback(__u32 index, void *data)  }  /* A direct read within a callback function should fail */ -SEC("?raw_tp/sys_nanosleep") +SEC("?raw_tp")  int invalid_read4(void *ctx)  {  	struct bpf_dynptr ptr; @@ -520,7 +556,7 @@ int invalid_read4(void *ctx)  }  /* Initializing a dynptr on an offset should fail */ -SEC("?raw_tp/sys_nanosleep") +SEC("?raw_tp")  int invalid_offset(void *ctx)  {  	struct bpf_dynptr ptr; @@ -534,7 +570,7 @@ int invalid_offset(void *ctx)  }  /* Can't release a dynptr twice */ -SEC("?raw_tp/sys_nanosleep") +SEC("?raw_tp")  int release_twice(void *ctx)  {  	struct bpf_dynptr ptr; @@ -560,7 +596,7 @@ static int release_twice_callback_fn(__u32 index, void *data)  /* Test that releasing a dynptr twice, where one of the releases happens   * within a calback function, fails   */ -SEC("?raw_tp/sys_nanosleep") +SEC("?raw_tp")  int release_twice_callback(void *ctx)  {  	struct bpf_dynptr ptr; @@ -575,7 +611,7 @@ int release_twice_callback(void *ctx)  }  /* Reject unsupported local mem types for dynptr_from_mem API */ -SEC("?raw_tp/sys_nanosleep") +SEC("?raw_tp")  int dynptr_from_mem_invalid_api(void *ctx)  {  	struct bpf_dynptr ptr;  |