Linux Audio

Check our new training course

In-person Linux kernel drivers training

Jun 16-20, 2025
Register
Loading...
Note: File does not exist in v4.6.
  1// SPDX-License-Identifier: GPL-2.0
  2/* Copyright (c) 2022 Meta Platforms, Inc. and affiliates.*/
  3
  4#define _GNU_SOURCE
  5#include <unistd.h>
  6#include <sys/syscall.h>
  7#include <sys/types.h>
  8#include <test_progs.h>
  9#include <bpf/btf.h>
 10#include "rcu_read_lock.skel.h"
 11#include "cgroup_helpers.h"
 12
 13static unsigned long long cgroup_id;
 14
 15static void test_success(void)
 16{
 17	struct rcu_read_lock *skel;
 18	int err;
 19
 20	skel = rcu_read_lock__open();
 21	if (!ASSERT_OK_PTR(skel, "skel_open"))
 22		return;
 23
 24	skel->bss->target_pid = sys_gettid();
 25
 26	bpf_program__set_autoload(skel->progs.get_cgroup_id, true);
 27	bpf_program__set_autoload(skel->progs.task_succ, true);
 28	bpf_program__set_autoload(skel->progs.two_regions, true);
 29	bpf_program__set_autoload(skel->progs.non_sleepable_1, true);
 30	bpf_program__set_autoload(skel->progs.non_sleepable_2, true);
 31	bpf_program__set_autoload(skel->progs.task_trusted_non_rcuptr, true);
 32	bpf_program__set_autoload(skel->progs.rcu_read_lock_subprog, true);
 33	bpf_program__set_autoload(skel->progs.rcu_read_lock_global_subprog, true);
 34	bpf_program__set_autoload(skel->progs.rcu_read_lock_subprog_lock, true);
 35	bpf_program__set_autoload(skel->progs.rcu_read_lock_subprog_unlock, true);
 36	err = rcu_read_lock__load(skel);
 37	if (!ASSERT_OK(err, "skel_load"))
 38		goto out;
 39
 40	err = rcu_read_lock__attach(skel);
 41	if (!ASSERT_OK(err, "skel_attach"))
 42		goto out;
 43
 44	syscall(SYS_getpgid);
 45
 46	ASSERT_EQ(skel->bss->task_storage_val, 2, "task_storage_val");
 47	ASSERT_EQ(skel->bss->cgroup_id, cgroup_id, "cgroup_id");
 48out:
 49	rcu_read_lock__destroy(skel);
 50}
 51
 52static void test_rcuptr_acquire(void)
 53{
 54	struct rcu_read_lock *skel;
 55	int err;
 56
 57	skel = rcu_read_lock__open();
 58	if (!ASSERT_OK_PTR(skel, "skel_open"))
 59		return;
 60
 61	skel->bss->target_pid = sys_gettid();
 62
 63	bpf_program__set_autoload(skel->progs.task_acquire, true);
 64	err = rcu_read_lock__load(skel);
 65	if (!ASSERT_OK(err, "skel_load"))
 66		goto out;
 67
 68	err = rcu_read_lock__attach(skel);
 69	ASSERT_OK(err, "skel_attach");
 70out:
 71	rcu_read_lock__destroy(skel);
 72}
 73
 74static const char * const inproper_region_tests[] = {
 75	"miss_lock",
 76	"no_lock",
 77	"miss_unlock",
 78	"non_sleepable_rcu_mismatch",
 79	"inproper_sleepable_helper",
 80	"inproper_sleepable_kfunc",
 81	"nested_rcu_region",
 82	"rcu_read_lock_global_subprog_lock",
 83	"rcu_read_lock_global_subprog_unlock",
 84};
 85
 86static void test_inproper_region(void)
 87{
 88	struct rcu_read_lock *skel;
 89	struct bpf_program *prog;
 90	int i, err;
 91
 92	for (i = 0; i < ARRAY_SIZE(inproper_region_tests); i++) {
 93		skel = rcu_read_lock__open();
 94		if (!ASSERT_OK_PTR(skel, "skel_open"))
 95			return;
 96
 97		prog = bpf_object__find_program_by_name(skel->obj, inproper_region_tests[i]);
 98		if (!ASSERT_OK_PTR(prog, "bpf_object__find_program_by_name"))
 99			goto out;
100		bpf_program__set_autoload(prog, true);
101		err = rcu_read_lock__load(skel);
102		ASSERT_ERR(err, "skel_load");
103out:
104		rcu_read_lock__destroy(skel);
105	}
106}
107
108static const char * const rcuptr_misuse_tests[] = {
109	"task_untrusted_rcuptr",
110	"cross_rcu_region",
111};
112
113static void test_rcuptr_misuse(void)
114{
115	struct rcu_read_lock *skel;
116	struct bpf_program *prog;
117	int i, err;
118
119	for (i = 0; i < ARRAY_SIZE(rcuptr_misuse_tests); i++) {
120		skel = rcu_read_lock__open();
121		if (!ASSERT_OK_PTR(skel, "skel_open"))
122			return;
123
124		prog = bpf_object__find_program_by_name(skel->obj, rcuptr_misuse_tests[i]);
125		if (!ASSERT_OK_PTR(prog, "bpf_object__find_program_by_name"))
126			goto out;
127		bpf_program__set_autoload(prog, true);
128		err = rcu_read_lock__load(skel);
129		ASSERT_ERR(err, "skel_load");
130out:
131		rcu_read_lock__destroy(skel);
132	}
133}
134
135void test_rcu_read_lock(void)
136{
137	int cgroup_fd;
138
139	cgroup_fd = test__join_cgroup("/rcu_read_lock");
140	if (!ASSERT_GE(cgroup_fd, 0, "join_cgroup /rcu_read_lock"))
141		goto out;
142
143	cgroup_id = get_cgroup_id("/rcu_read_lock");
144	if (test__start_subtest("success"))
145		test_success();
146	if (test__start_subtest("rcuptr_acquire"))
147		test_rcuptr_acquire();
148	if (test__start_subtest("negative_tests_inproper_region"))
149		test_inproper_region();
150	if (test__start_subtest("negative_tests_rcuptr_misuse"))
151		test_rcuptr_misuse();
152	close(cgroup_fd);
153out:;
154}