148671232SYonghong Song // SPDX-License-Identifier: GPL-2.0
248671232SYonghong Song /* Copyright (c) 2022 Meta Platforms, Inc. and affiliates.*/
348671232SYonghong Song
448671232SYonghong Song #define _GNU_SOURCE
548671232SYonghong Song #include <unistd.h>
648671232SYonghong Song #include <sys/syscall.h>
748671232SYonghong Song #include <sys/types.h>
848671232SYonghong Song #include <test_progs.h>
948671232SYonghong Song #include <bpf/btf.h>
1048671232SYonghong Song #include "rcu_read_lock.skel.h"
1148671232SYonghong Song #include "cgroup_helpers.h"
1248671232SYonghong Song
1348671232SYonghong Song static unsigned long long cgroup_id;
1448671232SYonghong Song
test_success(void)1548671232SYonghong Song static void test_success(void)
1648671232SYonghong Song {
1748671232SYonghong Song struct rcu_read_lock *skel;
1848671232SYonghong Song int err;
1948671232SYonghong Song
2048671232SYonghong Song skel = rcu_read_lock__open();
2148671232SYonghong Song if (!ASSERT_OK_PTR(skel, "skel_open"))
2248671232SYonghong Song return;
2348671232SYonghong Song
2448671232SYonghong Song skel->bss->target_pid = syscall(SYS_gettid);
2548671232SYonghong Song
2648671232SYonghong Song bpf_program__set_autoload(skel->progs.get_cgroup_id, true);
2748671232SYonghong Song bpf_program__set_autoload(skel->progs.task_succ, true);
2848671232SYonghong Song bpf_program__set_autoload(skel->progs.two_regions, true);
2948671232SYonghong Song bpf_program__set_autoload(skel->progs.non_sleepable_1, true);
3048671232SYonghong Song bpf_program__set_autoload(skel->progs.non_sleepable_2, true);
316fcd486bSAlexei Starovoitov bpf_program__set_autoload(skel->progs.task_trusted_non_rcuptr, true);
32*8be6a014SKumar Kartikeya Dwivedi bpf_program__set_autoload(skel->progs.rcu_read_lock_subprog, true);
33*8be6a014SKumar Kartikeya Dwivedi bpf_program__set_autoload(skel->progs.rcu_read_lock_global_subprog, true);
34*8be6a014SKumar Kartikeya Dwivedi bpf_program__set_autoload(skel->progs.rcu_read_lock_subprog_lock, true);
35*8be6a014SKumar Kartikeya Dwivedi bpf_program__set_autoload(skel->progs.rcu_read_lock_subprog_unlock, true);
3648671232SYonghong Song err = rcu_read_lock__load(skel);
3748671232SYonghong Song if (!ASSERT_OK(err, "skel_load"))
3848671232SYonghong Song goto out;
3948671232SYonghong Song
4048671232SYonghong Song err = rcu_read_lock__attach(skel);
4148671232SYonghong Song if (!ASSERT_OK(err, "skel_attach"))
4248671232SYonghong Song goto out;
4348671232SYonghong Song
4448671232SYonghong Song syscall(SYS_getpgid);
4548671232SYonghong Song
4648671232SYonghong Song ASSERT_EQ(skel->bss->task_storage_val, 2, "task_storage_val");
4748671232SYonghong Song ASSERT_EQ(skel->bss->cgroup_id, cgroup_id, "cgroup_id");
4848671232SYonghong Song out:
4948671232SYonghong Song rcu_read_lock__destroy(skel);
5048671232SYonghong Song }
5148671232SYonghong Song
test_rcuptr_acquire(void)5248671232SYonghong Song static void test_rcuptr_acquire(void)
5348671232SYonghong Song {
5448671232SYonghong Song struct rcu_read_lock *skel;
5548671232SYonghong Song int err;
5648671232SYonghong Song
5748671232SYonghong Song skel = rcu_read_lock__open();
5848671232SYonghong Song if (!ASSERT_OK_PTR(skel, "skel_open"))
5948671232SYonghong Song return;
6048671232SYonghong Song
6148671232SYonghong Song skel->bss->target_pid = syscall(SYS_gettid);
6248671232SYonghong Song
6348671232SYonghong Song bpf_program__set_autoload(skel->progs.task_acquire, true);
6448671232SYonghong Song err = rcu_read_lock__load(skel);
6548671232SYonghong Song if (!ASSERT_OK(err, "skel_load"))
6648671232SYonghong Song goto out;
6748671232SYonghong Song
6848671232SYonghong Song err = rcu_read_lock__attach(skel);
6948671232SYonghong Song ASSERT_OK(err, "skel_attach");
7048671232SYonghong Song out:
7148671232SYonghong Song rcu_read_lock__destroy(skel);
7248671232SYonghong Song }
7348671232SYonghong Song
7448671232SYonghong Song static const char * const inproper_region_tests[] = {
7548671232SYonghong Song "miss_lock",
766fcd486bSAlexei Starovoitov "no_lock",
7748671232SYonghong Song "miss_unlock",
7848671232SYonghong Song "non_sleepable_rcu_mismatch",
7948671232SYonghong Song "inproper_sleepable_helper",
8048671232SYonghong Song "inproper_sleepable_kfunc",
8148671232SYonghong Song "nested_rcu_region",
82*8be6a014SKumar Kartikeya Dwivedi "rcu_read_lock_global_subprog_lock",
83*8be6a014SKumar Kartikeya Dwivedi "rcu_read_lock_global_subprog_unlock",
8448671232SYonghong Song };
8548671232SYonghong Song
test_inproper_region(void)8648671232SYonghong Song static void test_inproper_region(void)
8748671232SYonghong Song {
8848671232SYonghong Song struct rcu_read_lock *skel;
8948671232SYonghong Song struct bpf_program *prog;
9048671232SYonghong Song int i, err;
9148671232SYonghong Song
9248671232SYonghong Song for (i = 0; i < ARRAY_SIZE(inproper_region_tests); i++) {
9348671232SYonghong Song skel = rcu_read_lock__open();
9448671232SYonghong Song if (!ASSERT_OK_PTR(skel, "skel_open"))
9548671232SYonghong Song return;
9648671232SYonghong Song
9748671232SYonghong Song prog = bpf_object__find_program_by_name(skel->obj, inproper_region_tests[i]);
9848671232SYonghong Song if (!ASSERT_OK_PTR(prog, "bpf_object__find_program_by_name"))
9948671232SYonghong Song goto out;
10048671232SYonghong Song bpf_program__set_autoload(prog, true);
10148671232SYonghong Song err = rcu_read_lock__load(skel);
10248671232SYonghong Song ASSERT_ERR(err, "skel_load");
10348671232SYonghong Song out:
10448671232SYonghong Song rcu_read_lock__destroy(skel);
10548671232SYonghong Song }
10648671232SYonghong Song }
10748671232SYonghong Song
10848671232SYonghong Song static const char * const rcuptr_misuse_tests[] = {
10948671232SYonghong Song "task_untrusted_rcuptr",
11048671232SYonghong Song "cross_rcu_region",
11148671232SYonghong Song };
11248671232SYonghong Song
test_rcuptr_misuse(void)11348671232SYonghong Song static void test_rcuptr_misuse(void)
11448671232SYonghong Song {
11548671232SYonghong Song struct rcu_read_lock *skel;
11648671232SYonghong Song struct bpf_program *prog;
11748671232SYonghong Song int i, err;
11848671232SYonghong Song
11948671232SYonghong Song for (i = 0; i < ARRAY_SIZE(rcuptr_misuse_tests); i++) {
12048671232SYonghong Song skel = rcu_read_lock__open();
12148671232SYonghong Song if (!ASSERT_OK_PTR(skel, "skel_open"))
12248671232SYonghong Song return;
12348671232SYonghong Song
12448671232SYonghong Song prog = bpf_object__find_program_by_name(skel->obj, rcuptr_misuse_tests[i]);
12548671232SYonghong Song if (!ASSERT_OK_PTR(prog, "bpf_object__find_program_by_name"))
12648671232SYonghong Song goto out;
12748671232SYonghong Song bpf_program__set_autoload(prog, true);
12848671232SYonghong Song err = rcu_read_lock__load(skel);
12948671232SYonghong Song ASSERT_ERR(err, "skel_load");
13048671232SYonghong Song out:
13148671232SYonghong Song rcu_read_lock__destroy(skel);
13248671232SYonghong Song }
13348671232SYonghong Song }
13448671232SYonghong Song
test_rcu_read_lock(void)13548671232SYonghong Song void test_rcu_read_lock(void)
13648671232SYonghong Song {
13748671232SYonghong Song int cgroup_fd;
13848671232SYonghong Song
13948671232SYonghong Song cgroup_fd = test__join_cgroup("/rcu_read_lock");
14048671232SYonghong Song if (!ASSERT_GE(cgroup_fd, 0, "join_cgroup /rcu_read_lock"))
14148671232SYonghong Song goto out;
14248671232SYonghong Song
14348671232SYonghong Song cgroup_id = get_cgroup_id("/rcu_read_lock");
14448671232SYonghong Song if (test__start_subtest("success"))
14548671232SYonghong Song test_success();
14648671232SYonghong Song if (test__start_subtest("rcuptr_acquire"))
14748671232SYonghong Song test_rcuptr_acquire();
14848671232SYonghong Song if (test__start_subtest("negative_tests_inproper_region"))
14948671232SYonghong Song test_inproper_region();
15048671232SYonghong Song if (test__start_subtest("negative_tests_rcuptr_misuse"))
15148671232SYonghong Song test_rcuptr_misuse();
15248671232SYonghong Song close(cgroup_fd);
1536fcd486bSAlexei Starovoitov out:;
15448671232SYonghong Song }
155