From: Andrii Nakryiko <andrii.nakryiko@gmail.com>
To: Jordan Rome <linux@jordanrome.com>
Cc: bpf@vger.kernel.org, linux-mm@kvack.org,
Alexei Starovoitov <ast@kernel.org>,
Daniel Borkmann <daniel@iogearbox.net>,
Andrii Nakryiko <andrii@kernel.org>,
Kernel Team <kernel-team@fb.com>,
Andrew Morton <akpm@linux-foundation.org>,
Shakeel Butt <shakeel.butt@linux.dev>
Subject: Re: [bpf-next v2 2/2] selftests/bpf: Add tests for bpf_copy_from_user_task_str
Date: Fri, 10 Jan 2025 14:01:18 -0800 [thread overview]
Message-ID: <CAEf4BzacGVVfstC+upqJm+JmzuhAYAht_g1ZfMBAPezgzEQtpQ@mail.gmail.com> (raw)
In-Reply-To: <20250107020632.170883-2-linux@jordanrome.com>
On Mon, Jan 6, 2025 at 6:20 PM Jordan Rome <linux@jordanrome.com> wrote:
>
> This adds tests for both the happy path and the
> error path (with and without the BPF_F_PAD_ZEROS flag).
>
> Signed-off-by: Jordan Rome <linux@jordanrome.com>
> ---
> .../selftests/bpf/prog_tests/bpf_iter.c | 7 +++
> .../selftests/bpf/prog_tests/read_vsyscall.c | 1 +
> .../selftests/bpf/progs/bpf_iter_tasks.c | 55 +++++++++++++++++++
> .../selftests/bpf/progs/read_vsyscall.c | 6 +-
> 4 files changed, 67 insertions(+), 2 deletions(-)
>
> diff --git a/tools/testing/selftests/bpf/prog_tests/bpf_iter.c b/tools/testing/selftests/bpf/prog_tests/bpf_iter.c
> index 6f1bfacd7375..8ed864793bd1 100644
> --- a/tools/testing/selftests/bpf/prog_tests/bpf_iter.c
> +++ b/tools/testing/selftests/bpf/prog_tests/bpf_iter.c
> @@ -34,6 +34,8 @@
> #include "bpf_iter_ksym.skel.h"
> #include "bpf_iter_sockmap.skel.h"
>
> +static char test_data[] = "test_data";
> +
> static void test_btf_id_or_null(void)
> {
> struct bpf_iter_test_kern3 *skel;
> @@ -328,12 +330,17 @@ static void test_task_sleepable(void)
> if (!ASSERT_OK_PTR(skel, "bpf_iter_tasks__open_and_load"))
> return;
>
> + skel->bss->user_ptr = test_data;
> do_dummy_read(skel->progs.dump_task_sleepable);
>
> ASSERT_GT(skel->bss->num_expected_failure_copy_from_user_task, 0,
> "num_expected_failure_copy_from_user_task");
> ASSERT_GT(skel->bss->num_success_copy_from_user_task, 0,
> "num_success_copy_from_user_task");
> + ASSERT_GT(skel->bss->num_expected_failure_copy_from_user_task_str, 0,
> + "num_expected_failure_copy_from_user_task_str");
> + ASSERT_GT(skel->bss->num_success_copy_from_user_task_str, 0,
> + "num_success_copy_from_user_task_str");
>
> bpf_iter_tasks__destroy(skel);
> }
> diff --git a/tools/testing/selftests/bpf/prog_tests/read_vsyscall.c b/tools/testing/selftests/bpf/prog_tests/read_vsyscall.c
> index c7b9ba8b1d06..a8d1eaa67020 100644
> --- a/tools/testing/selftests/bpf/prog_tests/read_vsyscall.c
> +++ b/tools/testing/selftests/bpf/prog_tests/read_vsyscall.c
> @@ -24,6 +24,7 @@ struct read_ret_desc {
> { .name = "copy_from_user", .ret = -EFAULT },
> { .name = "copy_from_user_task", .ret = -EFAULT },
> { .name = "copy_from_user_str", .ret = -EFAULT },
> + { .name = "copy_from_user_task_str", .ret = -EFAULT },
> };
>
> void test_read_vsyscall(void)
> diff --git a/tools/testing/selftests/bpf/progs/bpf_iter_tasks.c b/tools/testing/selftests/bpf/progs/bpf_iter_tasks.c
> index bc10c4e4b4fa..90691e34b915 100644
> --- a/tools/testing/selftests/bpf/progs/bpf_iter_tasks.c
> +++ b/tools/testing/selftests/bpf/progs/bpf_iter_tasks.c
> @@ -9,6 +9,7 @@ char _license[] SEC("license") = "GPL";
> uint32_t tid = 0;
> int num_unknown_tid = 0;
> int num_known_tid = 0;
> +void *user_ptr = 0;
>
> SEC("iter/task")
> int dump_task(struct bpf_iter__task *ctx)
> @@ -35,7 +36,9 @@ int dump_task(struct bpf_iter__task *ctx)
> }
>
> int num_expected_failure_copy_from_user_task = 0;
> +int num_expected_failure_copy_from_user_task_str = 0;
> int num_success_copy_from_user_task = 0;
> +int num_success_copy_from_user_task_str = 0;
>
> SEC("iter.s/task")
> int dump_task_sleepable(struct bpf_iter__task *ctx)
> @@ -44,6 +47,9 @@ int dump_task_sleepable(struct bpf_iter__task *ctx)
> struct task_struct *task = ctx->task;
> static const char info[] = " === END ===";
> struct pt_regs *regs;
> + char task_str1[10] = "aaaaaaaaaa";
> + char task_str2[10], task_str3[10];
> + char task_str4[20] = "aaaaaaaaaaaaaaaaaaaa";
> void *ptr;
> uint32_t user_data = 0;
> int ret;
> @@ -78,8 +84,57 @@ int dump_task_sleepable(struct bpf_iter__task *ctx)
> BPF_SEQ_PRINTF(seq, "%s\n", info);
> return 0;
> }
> +
> ++num_success_copy_from_user_task;
>
> + /* Read an invalid pointer and ensure we get an error */
> + ptr = NULL;
> + ret = bpf_copy_from_user_task_str((char *)task_str1, sizeof(task_str1), ptr, task, 0);
> + if (ret >= 0 || task_str1[9] != 'a') {
> + BPF_SEQ_PRINTF(seq, "%s\n", info);
> + return 0;
> + }
> +
> + /* Read an invalid pointer and ensure we get error with pad zeros flag */
> + ptr = NULL;
> + ret = bpf_copy_from_user_task_str((char *)task_str1, sizeof(task_str1), ptr, task, BPF_F_PAD_ZEROS);
> + if (ret >= 0 || task_str1[9] != '\0') {
> + BPF_SEQ_PRINTF(seq, "%s\n", info);
> + return 0;
> + }
> +
> + ++num_expected_failure_copy_from_user_task_str;
> +
> + /* Same length as the string */
> + ret = bpf_copy_from_user_task_str((char *)task_str2, 10, user_ptr, task, 0);
> + if (bpf_strncmp(task_str2, 10, "test_data\0") != 0 || ret != 10) {
> + BPF_SEQ_PRINTF(seq, "%s\n", info);
> + return 0;
> + }
> +
> + /* Shorter length than the string */
> + ret = bpf_copy_from_user_task_str((char *)task_str3, 9, user_ptr, task, 0);
> + if (bpf_strncmp(task_str3, 9, "test_dat\0") != 0 || ret != 9) {
> + BPF_SEQ_PRINTF(seq, "%s\n", info);
> + return 0;
> + }
> +
> + /* Longer length than the string */
> + ret = bpf_copy_from_user_task_str((char *)task_str4, 20, user_ptr, task, 0);
> + if (bpf_strncmp(task_str4, 10, "test_data\0") != 0 || ret != 10 || task_str4[sizeof(task_str4) - 1] != 'a') {
> + BPF_SEQ_PRINTF(seq, "%s\n", info);
> + return 0;
> + }
> +
> + /* Longer length than the string with pad zeros flag */
> + ret = bpf_copy_from_user_task_str((char *)task_str4, 20, user_ptr, task, BPF_F_PAD_ZEROS);
> + if (bpf_strncmp(task_str4, 10, "test_data\0") != 0 || ret != 10 || task_str4[sizeof(task_str4) - 1] != '\0') {
looks like a long string, please check 100 character limit
> + BPF_SEQ_PRINTF(seq, "%s\n", info);
> + return 0;
nit: this BPF_SEQ_PRINTF() + return 0 repetition is... repetitive :)
`goto drop_out;` maybe?
> + }
> +
> + ++num_success_copy_from_user_task_str;
> +
> if (ctx->meta->seq_num == 0)
> BPF_SEQ_PRINTF(seq, " tgid gid data\n");
>
> diff --git a/tools/testing/selftests/bpf/progs/read_vsyscall.c b/tools/testing/selftests/bpf/progs/read_vsyscall.c
> index 39ebef430059..623c1c5bd2d0 100644
> --- a/tools/testing/selftests/bpf/progs/read_vsyscall.c
> +++ b/tools/testing/selftests/bpf/progs/read_vsyscall.c
> @@ -8,14 +8,15 @@
>
> int target_pid = 0;
> void *user_ptr = 0;
> -int read_ret[9];
> +int read_ret[10];
>
> char _license[] SEC("license") = "GPL";
>
> /*
> - * This is the only kfunc, the others are helpers
> + * These are the kfuncs, the others are helpers
> */
> int bpf_copy_from_user_str(void *dst, u32, const void *, u64) __weak __ksym;
> +int bpf_copy_from_user_task_str(void *dst, u32, const void *, struct task_struct *, u64) __weak __ksym;
these definitions should be coming from vmlinux.h, no need to add them
manually anymore
>
> SEC("fentry/" SYS_PREFIX "sys_nanosleep")
> int do_probe_read(void *ctx)
> @@ -47,6 +48,7 @@ int do_copy_from_user(void *ctx)
> read_ret[7] = bpf_copy_from_user_task(buf, sizeof(buf), user_ptr,
> bpf_get_current_task_btf(), 0);
> read_ret[8] = bpf_copy_from_user_str((char *)buf, sizeof(buf), user_ptr, 0);
> + read_ret[9] = bpf_copy_from_user_task_str((char *)buf, sizeof(buf), user_ptr, bpf_get_current_task_btf(), 0);
please drop all those (char *) casts, in C any pointer is implicitly
castable to `void *` and `void *` is (implicitly) castable to any
other pointer. C++ is stricter, but in C it's canonical to not do
casting
>
> return 0;
> }
> --
> 2.43.5
>
next prev parent reply other threads:[~2025-01-10 22:01 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-01-07 2:06 [bpf-next v2 1/2] bpf: Add bpf_copy_from_user_task_str kfunc Jordan Rome
2025-01-07 2:06 ` [bpf-next v2 2/2] selftests/bpf: Add tests for bpf_copy_from_user_task_str Jordan Rome
2025-01-10 22:01 ` Andrii Nakryiko [this message]
2025-01-16 4:57 ` kernel test robot
2025-01-09 1:13 ` [bpf-next v2 1/2] bpf: Add bpf_copy_from_user_task_str kfunc kernel test robot
2025-01-10 0:48 ` kernel test robot
2025-01-10 21:50 ` Andrii Nakryiko
2025-01-17 2:22 ` Jordan Rome
2025-01-17 18:26 ` Andrii Nakryiko
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=CAEf4BzacGVVfstC+upqJm+JmzuhAYAht_g1ZfMBAPezgzEQtpQ@mail.gmail.com \
--to=andrii.nakryiko@gmail.com \
--cc=akpm@linux-foundation.org \
--cc=andrii@kernel.org \
--cc=ast@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=daniel@iogearbox.net \
--cc=kernel-team@fb.com \
--cc=linux-mm@kvack.org \
--cc=linux@jordanrome.com \
--cc=shakeel.butt@linux.dev \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox