Skip to content

Commit 457b0de

Browse files
ameryhungKernel Patches Daemon
authored andcommitted
selftests/bpf: Test ambiguous associated struct_ops
Add a test to make sure implicit struct_ops association does not break backward compatibility nor return incorrect struct_ops. struct_ops programs should still be allowed to be reused in different struct_ops map. The associated struct_ops map set implicitly however will be poisoned. Trying to read it through the helper bpf_prog_get_assoc_struct_ops() should result in a NULL pointer. While recursion of test_1() cannot happen due to the associated struct_ops being ambiguois, explicitly check for it to prevent stack overflow if the test regresses. Signed-off-by: Amery Hung <[email protected]>
1 parent 98c8ae4 commit 457b0de

File tree

2 files changed

+113
-0
lines changed

2 files changed

+113
-0
lines changed

tools/testing/selftests/bpf/prog_tests/test_struct_ops_assoc.c

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
#include <test_progs.h>
44
#include "struct_ops_assoc.skel.h"
5+
#include "struct_ops_assoc_reuse.skel.h"
56

67
static void test_st_ops_assoc(void)
78
{
@@ -65,8 +66,45 @@ static void test_st_ops_assoc(void)
6566
struct_ops_assoc__destroy(skel);
6667
}
6768

69+
static void test_st_ops_assoc_reuse(void)
70+
{
71+
struct struct_ops_assoc_reuse *skel = NULL;
72+
int err;
73+
74+
skel = struct_ops_assoc_reuse__open_and_load();
75+
if (!ASSERT_OK_PTR(skel, "struct_ops_assoc_reuse__open"))
76+
goto out;
77+
78+
err = bpf_program__assoc_struct_ops(skel->progs.syscall_prog_a,
79+
skel->maps.st_ops_map_a, NULL);
80+
ASSERT_OK(err, "bpf_program__assoc_struct_ops");
81+
82+
err = bpf_program__assoc_struct_ops(skel->progs.syscall_prog_b,
83+
skel->maps.st_ops_map_b, NULL);
84+
ASSERT_OK(err, "bpf_program__assoc_struct_ops");
85+
86+
err = struct_ops_assoc_reuse__attach(skel);
87+
if (!ASSERT_OK(err, "struct_ops_assoc__attach"))
88+
goto out;
89+
90+
/* run syscall_prog that calls .test_1 and checks return */
91+
err = bpf_prog_test_run_opts(bpf_program__fd(skel->progs.syscall_prog_a), NULL);
92+
ASSERT_OK(err, "bpf_prog_test_run_opts");
93+
94+
err = bpf_prog_test_run_opts(bpf_program__fd(skel->progs.syscall_prog_b), NULL);
95+
ASSERT_OK(err, "bpf_prog_test_run_opts");
96+
97+
ASSERT_EQ(skel->bss->test_err_a, 0, "skel->bss->test_err_a");
98+
ASSERT_EQ(skel->bss->test_err_b, 0, "skel->bss->test_err_b");
99+
100+
out:
101+
struct_ops_assoc_reuse__destroy(skel);
102+
}
103+
68104
void test_struct_ops_assoc(void)
69105
{
70106
if (test__start_subtest("st_ops_assoc"))
71107
test_st_ops_assoc();
108+
if (test__start_subtest("st_ops_assoc_reuse"))
109+
test_st_ops_assoc_reuse();
72110
}
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
3+
#include <vmlinux.h>
4+
#include <bpf/bpf_tracing.h>
5+
#include "bpf_misc.h"
6+
#include "../test_kmods/bpf_testmod.h"
7+
#include "../test_kmods/bpf_testmod_kfunc.h"
8+
9+
char _license[] SEC("license") = "GPL";
10+
11+
#define MAP_A_MAGIC 1234
12+
int test_err_a;
13+
int recur;
14+
15+
/*
16+
* test_1_a is reused. The kfunc should not be able to get the associated
17+
* struct_ops and call test_1 recursively as it is ambiguous.
18+
*/
19+
SEC("struct_ops")
20+
int BPF_PROG(test_1_a, struct st_ops_args *args)
21+
{
22+
int ret;
23+
24+
if (!recur) {
25+
recur++;
26+
ret = bpf_kfunc_multi_st_ops_test_1_prog_arg(args, NULL);
27+
if (ret != -1)
28+
test_err_a++;
29+
recur--;
30+
}
31+
32+
return MAP_A_MAGIC;
33+
}
34+
35+
/* Programs associated with st_ops_map_a */
36+
37+
SEC("syscall")
38+
int syscall_prog_a(void *ctx)
39+
{
40+
struct st_ops_args args = {};
41+
int ret;
42+
43+
ret = bpf_kfunc_multi_st_ops_test_1_prog_arg(&args, NULL);
44+
if (ret != MAP_A_MAGIC)
45+
test_err_a++;
46+
47+
return 0;
48+
}
49+
50+
SEC(".struct_ops.link")
51+
struct bpf_testmod_multi_st_ops st_ops_map_a = {
52+
.test_1 = (void *)test_1_a,
53+
};
54+
55+
/* Programs associated with st_ops_map_b */
56+
57+
int test_err_b;
58+
59+
SEC("syscall")
60+
int syscall_prog_b(void *ctx)
61+
{
62+
struct st_ops_args args = {};
63+
int ret;
64+
65+
ret = bpf_kfunc_multi_st_ops_test_1_prog_arg(&args, NULL);
66+
if (ret != MAP_A_MAGIC)
67+
test_err_b++;
68+
69+
return 0;
70+
}
71+
72+
SEC(".struct_ops.link")
73+
struct bpf_testmod_multi_st_ops st_ops_map_b = {
74+
.test_1 = (void *)test_1_a,
75+
};

0 commit comments

Comments
 (0)