forked from torvalds/linux
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
selftests/bpf: Add tests for bpf_rcu_read_lock()
Add a few positive/negative tests to test bpf_rcu_read_lock() and its corresponding verifier support. The new test will fail on s390x and aarch64, so an entry is added to each of their respective deny lists. Acked-by: Martin KaFai Lau <[email protected]> Signed-off-by: Yonghong Song <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Alexei Starovoitov <[email protected]>
- Loading branch information
1 parent
9bb00b2
commit 4867123
Showing
4 changed files
with
450 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,158 @@ | ||
// SPDX-License-Identifier: GPL-2.0 | ||
/* Copyright (c) 2022 Meta Platforms, Inc. and affiliates.*/ | ||
|
||
#define _GNU_SOURCE | ||
#include <unistd.h> | ||
#include <sys/syscall.h> | ||
#include <sys/types.h> | ||
#include <test_progs.h> | ||
#include <bpf/btf.h> | ||
#include "rcu_read_lock.skel.h" | ||
#include "cgroup_helpers.h" | ||
|
||
static unsigned long long cgroup_id; | ||
|
||
static void test_success(void) | ||
{ | ||
struct rcu_read_lock *skel; | ||
int err; | ||
|
||
skel = rcu_read_lock__open(); | ||
if (!ASSERT_OK_PTR(skel, "skel_open")) | ||
return; | ||
|
||
skel->bss->target_pid = syscall(SYS_gettid); | ||
|
||
bpf_program__set_autoload(skel->progs.get_cgroup_id, true); | ||
bpf_program__set_autoload(skel->progs.task_succ, true); | ||
bpf_program__set_autoload(skel->progs.no_lock, true); | ||
bpf_program__set_autoload(skel->progs.two_regions, true); | ||
bpf_program__set_autoload(skel->progs.non_sleepable_1, true); | ||
bpf_program__set_autoload(skel->progs.non_sleepable_2, true); | ||
err = rcu_read_lock__load(skel); | ||
if (!ASSERT_OK(err, "skel_load")) | ||
goto out; | ||
|
||
err = rcu_read_lock__attach(skel); | ||
if (!ASSERT_OK(err, "skel_attach")) | ||
goto out; | ||
|
||
syscall(SYS_getpgid); | ||
|
||
ASSERT_EQ(skel->bss->task_storage_val, 2, "task_storage_val"); | ||
ASSERT_EQ(skel->bss->cgroup_id, cgroup_id, "cgroup_id"); | ||
out: | ||
rcu_read_lock__destroy(skel); | ||
} | ||
|
||
static void test_rcuptr_acquire(void) | ||
{ | ||
struct rcu_read_lock *skel; | ||
int err; | ||
|
||
skel = rcu_read_lock__open(); | ||
if (!ASSERT_OK_PTR(skel, "skel_open")) | ||
return; | ||
|
||
skel->bss->target_pid = syscall(SYS_gettid); | ||
|
||
bpf_program__set_autoload(skel->progs.task_acquire, true); | ||
err = rcu_read_lock__load(skel); | ||
if (!ASSERT_OK(err, "skel_load")) | ||
goto out; | ||
|
||
err = rcu_read_lock__attach(skel); | ||
ASSERT_OK(err, "skel_attach"); | ||
out: | ||
rcu_read_lock__destroy(skel); | ||
} | ||
|
||
static const char * const inproper_region_tests[] = { | ||
"miss_lock", | ||
"miss_unlock", | ||
"non_sleepable_rcu_mismatch", | ||
"inproper_sleepable_helper", | ||
"inproper_sleepable_kfunc", | ||
"nested_rcu_region", | ||
}; | ||
|
||
static void test_inproper_region(void) | ||
{ | ||
struct rcu_read_lock *skel; | ||
struct bpf_program *prog; | ||
int i, err; | ||
|
||
for (i = 0; i < ARRAY_SIZE(inproper_region_tests); i++) { | ||
skel = rcu_read_lock__open(); | ||
if (!ASSERT_OK_PTR(skel, "skel_open")) | ||
return; | ||
|
||
prog = bpf_object__find_program_by_name(skel->obj, inproper_region_tests[i]); | ||
if (!ASSERT_OK_PTR(prog, "bpf_object__find_program_by_name")) | ||
goto out; | ||
bpf_program__set_autoload(prog, true); | ||
err = rcu_read_lock__load(skel); | ||
ASSERT_ERR(err, "skel_load"); | ||
out: | ||
rcu_read_lock__destroy(skel); | ||
} | ||
} | ||
|
||
static const char * const rcuptr_misuse_tests[] = { | ||
"task_untrusted_non_rcuptr", | ||
"task_untrusted_rcuptr", | ||
"cross_rcu_region", | ||
}; | ||
|
||
static void test_rcuptr_misuse(void) | ||
{ | ||
struct rcu_read_lock *skel; | ||
struct bpf_program *prog; | ||
int i, err; | ||
|
||
for (i = 0; i < ARRAY_SIZE(rcuptr_misuse_tests); i++) { | ||
skel = rcu_read_lock__open(); | ||
if (!ASSERT_OK_PTR(skel, "skel_open")) | ||
return; | ||
|
||
prog = bpf_object__find_program_by_name(skel->obj, rcuptr_misuse_tests[i]); | ||
if (!ASSERT_OK_PTR(prog, "bpf_object__find_program_by_name")) | ||
goto out; | ||
bpf_program__set_autoload(prog, true); | ||
err = rcu_read_lock__load(skel); | ||
ASSERT_ERR(err, "skel_load"); | ||
out: | ||
rcu_read_lock__destroy(skel); | ||
} | ||
} | ||
|
||
void test_rcu_read_lock(void) | ||
{ | ||
struct btf *vmlinux_btf; | ||
int cgroup_fd; | ||
|
||
vmlinux_btf = btf__load_vmlinux_btf(); | ||
if (!ASSERT_OK_PTR(vmlinux_btf, "could not load vmlinux BTF")) | ||
return; | ||
if (btf__find_by_name_kind(vmlinux_btf, "rcu", BTF_KIND_TYPE_TAG) < 0) { | ||
test__skip(); | ||
goto out; | ||
} | ||
|
||
cgroup_fd = test__join_cgroup("/rcu_read_lock"); | ||
if (!ASSERT_GE(cgroup_fd, 0, "join_cgroup /rcu_read_lock")) | ||
goto out; | ||
|
||
cgroup_id = get_cgroup_id("/rcu_read_lock"); | ||
if (test__start_subtest("success")) | ||
test_success(); | ||
if (test__start_subtest("rcuptr_acquire")) | ||
test_rcuptr_acquire(); | ||
if (test__start_subtest("negative_tests_inproper_region")) | ||
test_inproper_region(); | ||
if (test__start_subtest("negative_tests_rcuptr_misuse")) | ||
test_rcuptr_misuse(); | ||
close(cgroup_fd); | ||
out: | ||
btf__free(vmlinux_btf); | ||
} |
Oops, something went wrong.