Test that MEM_UNINIT doesn't allow writing dynptr stack slots. Next, also add a test triggering the memmove case for dynptr_read and dynptr_write. Signed-off-by: Kumar Kartikeya Dwivedi <memxor@xxxxxxxxx> --- .../testing/selftests/bpf/prog_tests/dynptr.c | 3 ++ .../testing/selftests/bpf/progs/dynptr_fail.c | 35 +++++++++++++++++++ .../selftests/bpf/progs/dynptr_success.c | 20 +++++++++++ 3 files changed, 58 insertions(+) diff --git a/tools/testing/selftests/bpf/prog_tests/dynptr.c b/tools/testing/selftests/bpf/prog_tests/dynptr.c index 947126d217bd..20910598a0a6 100644 --- a/tools/testing/selftests/bpf/prog_tests/dynptr.c +++ b/tools/testing/selftests/bpf/prog_tests/dynptr.c @@ -42,11 +42,14 @@ static struct { {"release_twice_callback", "arg 1 is an unacquired reference"}, {"dynptr_from_mem_invalid_api", "Unsupported reg type fp for bpf_dynptr_from_mem data"}, + {"dynptr_read_into_slot", "potential write to dynptr at off=-16"}, + {"uninit_write_into_slot", "potential write to dynptr at off=-16"}, /* success cases */ {"test_read_write", NULL}, {"test_data_slice", NULL}, {"test_ringbuf", NULL}, + {"test_overlap", NULL}, }; static void verify_fail(const char *prog_name, const char *expected_err_msg) diff --git a/tools/testing/selftests/bpf/progs/dynptr_fail.c b/tools/testing/selftests/bpf/progs/dynptr_fail.c index b0f08ff024fb..43a0ed3736a9 100644 --- a/tools/testing/selftests/bpf/progs/dynptr_fail.c +++ b/tools/testing/selftests/bpf/progs/dynptr_fail.c @@ -622,3 +622,38 @@ int dynptr_from_mem_invalid_api(void *ctx) return 0; } + +/* Reject writes to dynptr slot from bpf_dynptr_read */ +SEC("?raw_tp") +int dynptr_read_into_slot(void *ctx) +{ + union { + struct { + char _pad[48]; + struct bpf_dynptr ptr; + }; + char buf[64]; + } data; + + bpf_ringbuf_reserve_dynptr(&ringbuf, 64, 0, &data.ptr); + /* this should fail */ + bpf_dynptr_read(data.buf, sizeof(data.buf), &data.ptr, 0, 0); + + return 0; +} + +/* Reject writes to dynptr slot for uninit arg */ +SEC("?raw_tp") +int uninit_write_into_slot(void *ctx) +{ + struct { + char buf[64]; + struct bpf_dynptr ptr; + } data; + + bpf_ringbuf_reserve_dynptr(&ringbuf, 80, 0, &data.ptr); + /* this should fail */ + bpf_get_current_comm(data.buf, 80); + + return 0; +} diff --git a/tools/testing/selftests/bpf/progs/dynptr_success.c b/tools/testing/selftests/bpf/progs/dynptr_success.c index a3a6103c8569..401e924b15a0 100644 --- a/tools/testing/selftests/bpf/progs/dynptr_success.c +++ b/tools/testing/selftests/bpf/progs/dynptr_success.c @@ -162,3 +162,23 @@ int test_ringbuf(void *ctx) bpf_ringbuf_discard_dynptr(&ptr, 0); return 0; } + +SEC("tp/syscalls/sys_enter_nanosleep") +int test_overlap(void *ctx) +{ + struct bpf_dynptr ptr; + void *p; + + if (bpf_get_current_pid_tgid() >> 32 != pid) + return 0; + bpf_ringbuf_reserve_dynptr(&ringbuf, 16, 0, &ptr); + p = bpf_dynptr_data(&ptr, 0, 16); + if (!p) { + err = 1; + goto done; + } + bpf_dynptr_read(p + 1, 8, &ptr, 0, 0); +done: + bpf_ringbuf_discard_dynptr(&ptr, 0); + return 0; +} -- 2.38.0