From: Levi Zim rsworktech@outlook.com
This patch adds a test for probe_read_user_dynptr helper, which tests reading variable length of user memory into a ringbuf backed dynptr.
Signed-off-by: Levi Zim rsworktech@outlook.com --- tools/testing/selftests/bpf/prog_tests/dynptr.c | 2 ++ tools/testing/selftests/bpf/progs/dynptr_success.c | 36 +++++++++++++++++++++- 2 files changed, 37 insertions(+), 1 deletion(-)
diff --git a/tools/testing/selftests/bpf/prog_tests/dynptr.c b/tools/testing/selftests/bpf/prog_tests/dynptr.c index d9a25c2873b6ed4219e063845b1caf978a7016fd..a5a61a4c570d803bfca2af3f1a3b7d5eb0b8197f 100644 --- a/tools/testing/selftests/bpf/prog_tests/dynptr.c +++ b/tools/testing/selftests/bpf/prog_tests/dynptr.c @@ -32,6 +32,7 @@ static struct { {"test_dynptr_skb_strcmp", SETUP_SKB_PROG}, {"test_dynptr_skb_tp_btf", SETUP_SKB_PROG_TP}, {"test_probe_read_kernel_dynptr", SETUP_RINGBUF}, + {"test_probe_read_user_dynptr", SETUP_RINGBUF}, };
static int ringbuf_cb(void *ctx, void *data, size_t len) @@ -61,6 +62,7 @@ static void verify_success(const char *prog_name, enum test_setup_type setup_typ return;
skel->bss->pid = getpid(); + skel->bss->user_ptr = (void *)&skel->data->test_buf; skel->data->test_buf.length = 8;
prog = bpf_object__find_program_by_name(skel->obj, prog_name); diff --git a/tools/testing/selftests/bpf/progs/dynptr_success.c b/tools/testing/selftests/bpf/progs/dynptr_success.c index 64c698f83a37bfe924db93d36982a0a1c8defe62..5317860290dccb0862b6a0b94bb6f738c8d92835 100644 --- a/tools/testing/selftests/bpf/progs/dynptr_success.c +++ b/tools/testing/selftests/bpf/progs/dynptr_success.c @@ -576,7 +576,7 @@ struct { } test_buf = { .length = 0, .buf = "0123456789abcdef", -}; +}, *user_ptr;
SEC("?tp/syscalls/sys_enter_nanosleep") int test_probe_read_kernel_dynptr(void *ctx) @@ -605,3 +605,37 @@ int test_probe_read_kernel_dynptr(void *ctx) bpf_ringbuf_submit_dynptr(&ptr, 0); return 0; } + +SEC("?tp/syscalls/sys_enter_nanosleep") +int test_probe_read_user_dynptr(void *ctx) +{ + struct bpf_dynptr ptr; + int copy_len; + + if (bpf_get_current_pid_tgid() >> 32 != pid) + return 0; + + err = bpf_probe_read_user(©_len, sizeof(copy_len), &user_ptr->length); + if (err < 0 || copy_len < 0) { + err = 1; + return 1; + } + + if (copy_len > MAX_BUFFER_LEN) + copy_len = MAX_BUFFER_LEN; + + bpf_ringbuf_reserve_dynptr(&ringbuf, copy_len, 0, &ptr); + + if (-E2BIG != bpf_probe_read_user_dynptr(&ptr, 0, MAX_BUFFER_LEN + 1, + &user_ptr->buf, 0)) { + err = 2; + goto cleanup; + } + + err = bpf_probe_read_user_dynptr(&ptr, 0, copy_len, + &user_ptr->buf, 0); + +cleanup: + bpf_ringbuf_submit_dynptr(&ptr, 0); + return 0; +}