Commit dc444be8 authored by Joanne Koong's avatar Joanne Koong Committed by Alexei Starovoitov

selftests/bpf: add extra test for using dynptr data slice after release

Add an additional test, "data_slice_use_after_release2", for ensuring
that data slices are correctly invalidated by the verifier after the
dynptr whose ref obj id they track is released. In particular, this
tests data slice invalidation for dynptrs located at a non-zero offset
from the frame pointer.
Signed-off-by: default avatarJoanne Koong <joannelkoong@gmail.com>
Acked-by: default avatarMartin KaFai Lau <kafai@fb.com>
Link: https://lore.kernel.org/r/20220809214055.4050604-2-joannelkoong@gmail.comSigned-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
parent 88374342
...@@ -22,7 +22,8 @@ static struct { ...@@ -22,7 +22,8 @@ static struct {
{"add_dynptr_to_map2", "invalid indirect read from stack"}, {"add_dynptr_to_map2", "invalid indirect read from stack"},
{"data_slice_out_of_bounds_ringbuf", "value is outside of the allowed memory range"}, {"data_slice_out_of_bounds_ringbuf", "value is outside of the allowed memory range"},
{"data_slice_out_of_bounds_map_value", "value is outside of the allowed memory range"}, {"data_slice_out_of_bounds_map_value", "value is outside of the allowed memory range"},
{"data_slice_use_after_release", "invalid mem access 'scalar'"}, {"data_slice_use_after_release1", "invalid mem access 'scalar'"},
{"data_slice_use_after_release2", "invalid mem access 'scalar'"},
{"data_slice_missing_null_check1", "invalid mem access 'mem_or_null'"}, {"data_slice_missing_null_check1", "invalid mem access 'mem_or_null'"},
{"data_slice_missing_null_check2", "invalid mem access 'mem_or_null'"}, {"data_slice_missing_null_check2", "invalid mem access 'mem_or_null'"},
{"invalid_helper1", "invalid indirect read from stack"}, {"invalid_helper1", "invalid indirect read from stack"},
......
...@@ -248,7 +248,7 @@ int data_slice_out_of_bounds_map_value(void *ctx) ...@@ -248,7 +248,7 @@ int data_slice_out_of_bounds_map_value(void *ctx)
/* A data slice can't be used after it has been released */ /* A data slice can't be used after it has been released */
SEC("?raw_tp") SEC("?raw_tp")
int data_slice_use_after_release(void *ctx) int data_slice_use_after_release1(void *ctx)
{ {
struct bpf_dynptr ptr; struct bpf_dynptr ptr;
struct sample *sample; struct sample *sample;
...@@ -272,6 +272,42 @@ int data_slice_use_after_release(void *ctx) ...@@ -272,6 +272,42 @@ int data_slice_use_after_release(void *ctx)
return 0; 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 */ /* A data slice must be first checked for NULL */
SEC("?raw_tp") SEC("?raw_tp")
int data_slice_missing_null_check1(void *ctx) int data_slice_missing_null_check1(void *ctx)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment