Split the test into two subtests: one for checking bpf_probe_read* of a vsyscall page from a non-sleepable probe and one for checking bpf_copy_from_user* of a vsyscall page from a sleepable probe. The split is useful for running the test on kernels which do not support sleepable fentry programs to allow skipping just a part of the test. Signed-off-by: Viktor Malik --- .../selftests/bpf/prog_tests/read_vsyscall.c | 41 ++++++++++++++++--- .../selftests/bpf/progs/read_vsyscall.c | 18 ++++---- 2 files changed, 44 insertions(+), 15 deletions(-) diff --git a/tools/testing/selftests/bpf/prog_tests/read_vsyscall.c b/tools/testing/selftests/bpf/prog_tests/read_vsyscall.c index a8d1eaa67020..bbacd1309046 100644 --- a/tools/testing/selftests/bpf/prog_tests/read_vsyscall.c +++ b/tools/testing/selftests/bpf/prog_tests/read_vsyscall.c @@ -14,22 +14,30 @@ struct read_ret_desc { const char *name; int ret; -} all_read[] = { +}; + +struct read_ret_desc all_probe_read[] = { { .name = "probe_read_kernel", .ret = -ERANGE }, { .name = "probe_read_kernel_str", .ret = -ERANGE }, { .name = "probe_read", .ret = -ERANGE }, { .name = "probe_read_str", .ret = -ERANGE }, { .name = "probe_read_user", .ret = -EFAULT }, { .name = "probe_read_user_str", .ret = -EFAULT }, +}; + +struct read_ret_desc all_copy_from_user[] = { { .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) +static void test_read_vsyscall_subtest(const char *prog_name, + const struct read_ret_desc *descs, + unsigned int cnt) { struct read_vsyscall *skel; + struct bpf_program *prog; unsigned int i; int err; @@ -37,10 +45,19 @@ void test_read_vsyscall(void) test__skip(); return; #endif - skel = read_vsyscall__open_and_load(); - if (!ASSERT_OK_PTR(skel, "read_vsyscall open_load")) + skel = read_vsyscall__open(); + if (!ASSERT_OK_PTR(skel, "read_vsyscall open")) return; + prog = bpf_object__find_program_by_name(skel->obj, prog_name); + if (!ASSERT_OK_PTR(prog, "read_vsyscall find program")) + goto out; + bpf_program__set_autoload(prog, true); + + err = read_vsyscall__load(skel); + if (!ASSERT_EQ(err, 0, "read_vsyscall load")) + goto out; + skel->bss->target_pid = getpid(); err = read_vsyscall__attach(skel); if (!ASSERT_EQ(err, 0, "read_vsyscall attach")) @@ -52,8 +69,20 @@ void test_read_vsyscall(void) skel->bss->user_ptr = (void *)VSYSCALL_ADDR; usleep(1); - for (i = 0; i < ARRAY_SIZE(all_read); i++) - ASSERT_EQ(skel->bss->read_ret[i], all_read[i].ret, all_read[i].name); + for (i = 0; i < cnt; i++) + ASSERT_EQ(skel->bss->read_ret[i], descs[i].ret, descs[i].name); out: read_vsyscall__destroy(skel); } + +void test_read_vsyscall(void) +{ + if (test__start_subtest("probe_read")) { + test_read_vsyscall_subtest("probe_read", all_probe_read, + ARRAY_SIZE(all_probe_read)); + } + if (test__start_subtest("copy_from_user")) { + test_read_vsyscall_subtest("copy_from_user", all_copy_from_user, + ARRAY_SIZE(all_copy_from_user)); + } +} diff --git a/tools/testing/selftests/bpf/progs/read_vsyscall.c b/tools/testing/selftests/bpf/progs/read_vsyscall.c index 395591374d4f..45bcf923ec70 100644 --- a/tools/testing/selftests/bpf/progs/read_vsyscall.c +++ b/tools/testing/selftests/bpf/progs/read_vsyscall.c @@ -8,7 +8,7 @@ int target_pid = 0; void *user_ptr = 0; -int read_ret[10]; +int read_ret[6]; char _license[] SEC("license") = "GPL"; @@ -19,8 +19,8 @@ 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; -SEC("fentry/" SYS_PREFIX "sys_nanosleep") -int do_probe_read(void *ctx) +SEC("?fentry/" SYS_PREFIX "sys_nanosleep") +int probe_read(void *ctx) { char buf[8]; @@ -37,19 +37,19 @@ int do_probe_read(void *ctx) return 0; } -SEC("fentry.s/" SYS_PREFIX "sys_nanosleep") -int do_copy_from_user(void *ctx) +SEC("?fentry.s/" SYS_PREFIX "sys_nanosleep") +int copy_from_user(void *ctx) { char buf[8]; if ((bpf_get_current_pid_tgid() >> 32) != target_pid) return 0; - read_ret[6] = bpf_copy_from_user(buf, sizeof(buf), user_ptr); - read_ret[7] = bpf_copy_from_user_task(buf, sizeof(buf), user_ptr, + read_ret[0] = bpf_copy_from_user(buf, sizeof(buf), user_ptr); + read_ret[1] = 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, + read_ret[2] = bpf_copy_from_user_str((char *)buf, sizeof(buf), user_ptr, 0); + read_ret[3] = bpf_copy_from_user_task_str((char *)buf, sizeof(buf), user_ptr, bpf_get_current_task_btf(), -- 2.53.0