]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
selftests/bpf: Add tests for bpf_task_from_vpid() kfunc
authorJuntong Deng <juntong.deng@outlook.com>
Mon, 14 Oct 2024 09:25:53 +0000 (10:25 +0100)
committerAlexei Starovoitov <ast@kernel.org>
Wed, 16 Oct 2024 16:21:18 +0000 (09:21 -0700)
This patch adds test cases for bpf_task_from_vpid() kfunc.

task_kfunc_from_vpid_no_null_check is used to test the case where
the return value is not checked for NULL pointer.

test_task_from_vpid_current is used to test obtaining the
struct task_struct of the process in the pid namespace based on vpid.

test_task_from_vpid_invalid is used to test the case of invalid vpid.

test_task_from_vpid_current and test_task_from_vpid_invalid will run
in the new namespace.

Signed-off-by: Juntong Deng <juntong.deng@outlook.com>
Link: https://lore.kernel.org/r/AM6PR03MB5848F13435CD650AC4B7BD7099442@AM6PR03MB5848.eurprd03.prod.outlook.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
tools/testing/selftests/bpf/prog_tests/task_kfunc.c
tools/testing/selftests/bpf/progs/task_kfunc_common.h
tools/testing/selftests/bpf/progs/task_kfunc_failure.c
tools/testing/selftests/bpf/progs/task_kfunc_success.c

index d4579f735398c805bc0470c6e06438910e5acb58..83b90335967a52e99a21099be5e50aeadde95f6d 100644 (file)
@@ -68,6 +68,74 @@ cleanup:
        task_kfunc_success__destroy(skel);
 }
 
+static int run_vpid_test(void *prog_name)
+{
+       struct task_kfunc_success *skel;
+       struct bpf_program *prog;
+       int prog_fd, err = 0;
+
+       if (getpid() != 1)
+               return 1;
+
+       skel = open_load_task_kfunc_skel();
+       if (!skel)
+               return 2;
+
+       if (skel->bss->err) {
+               err = 3;
+               goto cleanup;
+       }
+
+       prog = bpf_object__find_program_by_name(skel->obj, prog_name);
+       if (!prog) {
+               err = 4;
+               goto cleanup;
+       }
+
+       prog_fd = bpf_program__fd(prog);
+       if (prog_fd < 0) {
+               err = 5;
+               goto cleanup;
+       }
+
+       if (bpf_prog_test_run_opts(prog_fd, NULL)) {
+               err = 6;
+               goto cleanup;
+       }
+
+       if (skel->bss->err)
+               err = 7 + skel->bss->err;
+cleanup:
+       task_kfunc_success__destroy(skel);
+       return err;
+}
+
+static void run_vpid_success_test(const char *prog_name)
+{
+       const int stack_size = 1024 * 1024;
+       int child_pid, wstatus;
+       char *stack;
+
+       stack = (char *)malloc(stack_size);
+       if (!ASSERT_OK_PTR(stack, "clone_stack"))
+               return;
+
+       child_pid = clone(run_vpid_test, stack + stack_size,
+                         CLONE_NEWPID | SIGCHLD, (void *)prog_name);
+       if (!ASSERT_GT(child_pid, -1, "child_pid"))
+               goto cleanup;
+
+       if (!ASSERT_GT(waitpid(child_pid, &wstatus, 0), -1, "waitpid"))
+               goto cleanup;
+
+       if (WEXITSTATUS(wstatus) > 7)
+               ASSERT_OK(WEXITSTATUS(wstatus) - 7, "vpid_test_failure");
+       else
+               ASSERT_OK(WEXITSTATUS(wstatus), "run_vpid_test_err");
+cleanup:
+       free(stack);
+}
+
 static const char * const success_tests[] = {
        "test_task_acquire_release_argument",
        "test_task_acquire_release_current",
@@ -83,6 +151,11 @@ static const char * const success_tests[] = {
        "test_task_kfunc_flavor_relo_not_found",
 };
 
+static const char * const vpid_success_tests[] = {
+       "test_task_from_vpid_current",
+       "test_task_from_vpid_invalid",
+};
+
 void test_task_kfunc(void)
 {
        int i;
@@ -94,5 +167,12 @@ void test_task_kfunc(void)
                run_success_test(success_tests[i]);
        }
 
+       for (i = 0; i < ARRAY_SIZE(vpid_success_tests); i++) {
+               if (!test__start_subtest(vpid_success_tests[i]))
+                       continue;
+
+               run_vpid_success_test(vpid_success_tests[i]);
+       }
+
        RUN_TESTS(task_kfunc_failure);
 }
index 6720c4b5be414df23f1987cf6f053d34fb77d046..e9c4fea7a4bbaf3d67b833e34eacd28426c24659 100644 (file)
@@ -23,6 +23,7 @@ struct {
 struct task_struct *bpf_task_acquire(struct task_struct *p) __ksym;
 void bpf_task_release(struct task_struct *p) __ksym;
 struct task_struct *bpf_task_from_pid(s32 pid) __ksym;
+struct task_struct *bpf_task_from_vpid(s32 vpid) __ksym;
 void bpf_rcu_read_lock(void) __ksym;
 void bpf_rcu_read_unlock(void) __ksym;
 
index ad88a3796ddff28b28d19cf190a8867618d5cd50..4c07ea193f721d4799921c5950acd49428bf8bd2 100644 (file)
@@ -247,6 +247,20 @@ int BPF_PROG(task_kfunc_from_pid_no_null_check, struct task_struct *task, u64 cl
        return 0;
 }
 
+SEC("tp_btf/task_newtask")
+__failure __msg("Possibly NULL pointer passed to trusted arg0")
+int BPF_PROG(task_kfunc_from_vpid_no_null_check, struct task_struct *task, u64 clone_flags)
+{
+       struct task_struct *acquired;
+
+       acquired = bpf_task_from_vpid(task->pid);
+
+       /* Releasing bpf_task_from_vpid() lookup without a NULL check. */
+       bpf_task_release(acquired);
+
+       return 0;
+}
+
 SEC("lsm/task_free")
 __failure __msg("R1 must be a rcu pointer")
 int BPF_PROG(task_kfunc_from_lsm_task_free, struct task_struct *task)
index a551490150630a43be0691cf48b3a76f29a67eff..5fb4fc19d26a8d42c180a9a76f9a8e9650eb2212 100644 (file)
@@ -366,3 +366,54 @@ int BPF_PROG(task_kfunc_acquire_trusted_walked, struct task_struct *task, u64 cl
 
        return 0;
 }
+
+SEC("syscall")
+int test_task_from_vpid_current(const void *ctx)
+{
+       struct task_struct *current, *v_task;
+
+       v_task = bpf_task_from_vpid(1);
+       if (!v_task) {
+               err = 1;
+               return 0;
+       }
+
+       current = bpf_get_current_task_btf();
+
+       /* The current process should be the init process (pid 1) in the new pid namespace. */
+       if (current != v_task)
+               err = 2;
+
+       bpf_task_release(v_task);
+       return 0;
+}
+
+SEC("syscall")
+int test_task_from_vpid_invalid(const void *ctx)
+{
+       struct task_struct *v_task;
+
+       v_task = bpf_task_from_vpid(-1);
+       if (v_task) {
+               err = 1;
+               goto err;
+       }
+
+       /* There should be only one process (current process) in the new pid namespace. */
+       v_task = bpf_task_from_vpid(2);
+       if (v_task) {
+               err = 2;
+               goto err;
+       }
+
+       v_task = bpf_task_from_vpid(9999);
+       if (v_task) {
+               err = 3;
+               goto err;
+       }
+
+       return 0;
+err:
+       bpf_task_release(v_task);
+       return 0;
+}