Skip to content

Commit a2c6380

Browse files
laoarMartin KaFai Lau
authored and
Martin KaFai Lau
committed
selftests/bpf: Add selftests for cgroup1 local storage
Expanding the test coverage from cgroup2 to include cgroup1. The result as follows, Already existing test cases for cgroup2: #48/1 cgrp_local_storage/tp_btf:OK #48/2 cgrp_local_storage/attach_cgroup:OK #48/3 cgrp_local_storage/recursion:OK #48/4 cgrp_local_storage/negative:OK #48/5 cgrp_local_storage/cgroup_iter_sleepable:OK #48/6 cgrp_local_storage/yes_rcu_lock:OK #48/7 cgrp_local_storage/no_rcu_lock:OK Expanded test cases for cgroup1: #48/8 cgrp_local_storage/cgrp1_tp_btf:OK #48/9 cgrp_local_storage/cgrp1_recursion:OK #48/10 cgrp_local_storage/cgrp1_negative:OK #48/11 cgrp_local_storage/cgrp1_iter_sleepable:OK #48/12 cgrp_local_storage/cgrp1_yes_rcu_lock:OK #48/13 cgrp_local_storage/cgrp1_no_rcu_lock:OK Summary: #48 cgrp_local_storage:OK Summary: 1/13 PASSED, 0 SKIPPED, 0 FAILED Signed-off-by: Yafang Shao <[email protected]> Acked-by: Tejun Heo <[email protected]> Acked-by: Yonghong Song <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Martin KaFai Lau <[email protected]>
1 parent f419927 commit a2c6380

File tree

4 files changed

+278
-47
lines changed

4 files changed

+278
-47
lines changed

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

+97-1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,21 @@ struct socket_cookie {
1919
__u64 cookie_value;
2020
};
2121

22+
static bool is_cgroup1;
23+
static int target_hid;
24+
25+
#define CGROUP_MODE_SET(skel) \
26+
{ \
27+
skel->bss->is_cgroup1 = is_cgroup1; \
28+
skel->bss->target_hid = target_hid; \
29+
}
30+
31+
static void cgroup_mode_value_init(bool cgroup, int hid)
32+
{
33+
is_cgroup1 = cgroup;
34+
target_hid = hid;
35+
}
36+
2237
static void test_tp_btf(int cgroup_fd)
2338
{
2439
struct cgrp_ls_tp_btf *skel;
@@ -29,6 +44,8 @@ static void test_tp_btf(int cgroup_fd)
2944
if (!ASSERT_OK_PTR(skel, "skel_open_and_load"))
3045
return;
3146

47+
CGROUP_MODE_SET(skel);
48+
3249
/* populate a value in map_b */
3350
err = bpf_map_update_elem(bpf_map__fd(skel->maps.map_b), &cgroup_fd, &val1, BPF_ANY);
3451
if (!ASSERT_OK(err, "map_update_elem"))
@@ -130,6 +147,8 @@ static void test_recursion(int cgroup_fd)
130147
if (!ASSERT_OK_PTR(skel, "skel_open_and_load"))
131148
return;
132149

150+
CGROUP_MODE_SET(skel);
151+
133152
err = cgrp_ls_recursion__attach(skel);
134153
if (!ASSERT_OK(err, "skel_attach"))
135154
goto out;
@@ -165,6 +184,8 @@ static void test_cgroup_iter_sleepable(int cgroup_fd, __u64 cgroup_id)
165184
if (!ASSERT_OK_PTR(skel, "skel_open"))
166185
return;
167186

187+
CGROUP_MODE_SET(skel);
188+
168189
bpf_program__set_autoload(skel->progs.cgroup_iter, true);
169190
err = cgrp_ls_sleepable__load(skel);
170191
if (!ASSERT_OK(err, "skel_load"))
@@ -202,6 +223,7 @@ static void test_yes_rcu_lock(__u64 cgroup_id)
202223
if (!ASSERT_OK_PTR(skel, "skel_open"))
203224
return;
204225

226+
CGROUP_MODE_SET(skel);
205227
skel->bss->target_pid = syscall(SYS_gettid);
206228

207229
bpf_program__set_autoload(skel->progs.yes_rcu_lock, true);
@@ -229,14 +251,34 @@ static void test_no_rcu_lock(void)
229251
if (!ASSERT_OK_PTR(skel, "skel_open"))
230252
return;
231253

254+
CGROUP_MODE_SET(skel);
255+
232256
bpf_program__set_autoload(skel->progs.no_rcu_lock, true);
233257
err = cgrp_ls_sleepable__load(skel);
234258
ASSERT_ERR(err, "skel_load");
235259

236260
cgrp_ls_sleepable__destroy(skel);
237261
}
238262

239-
void test_cgrp_local_storage(void)
263+
static void test_cgrp1_no_rcu_lock(void)
264+
{
265+
struct cgrp_ls_sleepable *skel;
266+
int err;
267+
268+
skel = cgrp_ls_sleepable__open();
269+
if (!ASSERT_OK_PTR(skel, "skel_open"))
270+
return;
271+
272+
CGROUP_MODE_SET(skel);
273+
274+
bpf_program__set_autoload(skel->progs.cgrp1_no_rcu_lock, true);
275+
err = cgrp_ls_sleepable__load(skel);
276+
ASSERT_OK(err, "skel_load");
277+
278+
cgrp_ls_sleepable__destroy(skel);
279+
}
280+
281+
static void cgrp2_local_storage(void)
240282
{
241283
__u64 cgroup_id;
242284
int cgroup_fd;
@@ -245,6 +287,8 @@ void test_cgrp_local_storage(void)
245287
if (!ASSERT_GE(cgroup_fd, 0, "join_cgroup /cgrp_local_storage"))
246288
return;
247289

290+
cgroup_mode_value_init(0, -1);
291+
248292
cgroup_id = get_cgroup_id("/cgrp_local_storage");
249293
if (test__start_subtest("tp_btf"))
250294
test_tp_btf(cgroup_fd);
@@ -263,3 +307,55 @@ void test_cgrp_local_storage(void)
263307

264308
close(cgroup_fd);
265309
}
310+
311+
static void cgrp1_local_storage(void)
312+
{
313+
int cgrp1_fd, cgrp1_hid, cgrp1_id, err;
314+
315+
/* Setup cgroup1 hierarchy */
316+
err = setup_classid_environment();
317+
if (!ASSERT_OK(err, "setup_classid_environment"))
318+
return;
319+
320+
err = join_classid();
321+
if (!ASSERT_OK(err, "join_cgroup1"))
322+
goto cleanup;
323+
324+
cgrp1_fd = open_classid();
325+
if (!ASSERT_GE(cgrp1_fd, 0, "cgroup1 fd"))
326+
goto cleanup;
327+
328+
cgrp1_id = get_classid_cgroup_id();
329+
if (!ASSERT_GE(cgrp1_id, 0, "cgroup1 id"))
330+
goto close_fd;
331+
332+
cgrp1_hid = get_cgroup1_hierarchy_id("net_cls");
333+
if (!ASSERT_GE(cgrp1_hid, 0, "cgroup1 hid"))
334+
goto close_fd;
335+
336+
cgroup_mode_value_init(1, cgrp1_hid);
337+
338+
if (test__start_subtest("cgrp1_tp_btf"))
339+
test_tp_btf(cgrp1_fd);
340+
if (test__start_subtest("cgrp1_recursion"))
341+
test_recursion(cgrp1_fd);
342+
if (test__start_subtest("cgrp1_negative"))
343+
test_negative();
344+
if (test__start_subtest("cgrp1_iter_sleepable"))
345+
test_cgroup_iter_sleepable(cgrp1_fd, cgrp1_id);
346+
if (test__start_subtest("cgrp1_yes_rcu_lock"))
347+
test_yes_rcu_lock(cgrp1_id);
348+
if (test__start_subtest("cgrp1_no_rcu_lock"))
349+
test_cgrp1_no_rcu_lock();
350+
351+
close_fd:
352+
close(cgrp1_fd);
353+
cleanup:
354+
cleanup_classid_environment();
355+
}
356+
357+
void test_cgrp_local_storage(void)
358+
{
359+
cgrp2_local_storage();
360+
cgrp1_local_storage();
361+
}

tools/testing/selftests/bpf/progs/cgrp_ls_recursion.c

+67-17
Original file line numberDiff line numberDiff line change
@@ -21,50 +21,100 @@ struct {
2121
__type(value, long);
2222
} map_b SEC(".maps");
2323

24+
int target_hid = 0;
25+
bool is_cgroup1 = 0;
26+
27+
struct cgroup *bpf_task_get_cgroup1(struct task_struct *task, int hierarchy_id) __ksym;
28+
void bpf_cgroup_release(struct cgroup *cgrp) __ksym;
29+
30+
static void __on_lookup(struct cgroup *cgrp)
31+
{
32+
bpf_cgrp_storage_delete(&map_a, cgrp);
33+
bpf_cgrp_storage_delete(&map_b, cgrp);
34+
}
35+
2436
SEC("fentry/bpf_local_storage_lookup")
2537
int BPF_PROG(on_lookup)
2638
{
2739
struct task_struct *task = bpf_get_current_task_btf();
40+
struct cgroup *cgrp;
41+
42+
if (is_cgroup1) {
43+
cgrp = bpf_task_get_cgroup1(task, target_hid);
44+
if (!cgrp)
45+
return 0;
2846

29-
bpf_cgrp_storage_delete(&map_a, task->cgroups->dfl_cgrp);
30-
bpf_cgrp_storage_delete(&map_b, task->cgroups->dfl_cgrp);
47+
__on_lookup(cgrp);
48+
bpf_cgroup_release(cgrp);
49+
return 0;
50+
}
51+
52+
__on_lookup(task->cgroups->dfl_cgrp);
3153
return 0;
3254
}
3355

34-
SEC("fentry/bpf_local_storage_update")
35-
int BPF_PROG(on_update)
56+
static void __on_update(struct cgroup *cgrp)
3657
{
37-
struct task_struct *task = bpf_get_current_task_btf();
3858
long *ptr;
3959

40-
ptr = bpf_cgrp_storage_get(&map_a, task->cgroups->dfl_cgrp, 0,
41-
BPF_LOCAL_STORAGE_GET_F_CREATE);
60+
ptr = bpf_cgrp_storage_get(&map_a, cgrp, 0, BPF_LOCAL_STORAGE_GET_F_CREATE);
4261
if (ptr)
4362
*ptr += 1;
4463

45-
ptr = bpf_cgrp_storage_get(&map_b, task->cgroups->dfl_cgrp, 0,
46-
BPF_LOCAL_STORAGE_GET_F_CREATE);
64+
ptr = bpf_cgrp_storage_get(&map_b, cgrp, 0, BPF_LOCAL_STORAGE_GET_F_CREATE);
4765
if (ptr)
4866
*ptr += 1;
67+
}
4968

69+
SEC("fentry/bpf_local_storage_update")
70+
int BPF_PROG(on_update)
71+
{
72+
struct task_struct *task = bpf_get_current_task_btf();
73+
struct cgroup *cgrp;
74+
75+
if (is_cgroup1) {
76+
cgrp = bpf_task_get_cgroup1(task, target_hid);
77+
if (!cgrp)
78+
return 0;
79+
80+
__on_update(cgrp);
81+
bpf_cgroup_release(cgrp);
82+
return 0;
83+
}
84+
85+
__on_update(task->cgroups->dfl_cgrp);
5086
return 0;
5187
}
5288

53-
SEC("tp_btf/sys_enter")
54-
int BPF_PROG(on_enter, struct pt_regs *regs, long id)
89+
static void __on_enter(struct pt_regs *regs, long id, struct cgroup *cgrp)
5590
{
56-
struct task_struct *task;
5791
long *ptr;
5892

59-
task = bpf_get_current_task_btf();
60-
ptr = bpf_cgrp_storage_get(&map_a, task->cgroups->dfl_cgrp, 0,
61-
BPF_LOCAL_STORAGE_GET_F_CREATE);
93+
ptr = bpf_cgrp_storage_get(&map_a, cgrp, 0, BPF_LOCAL_STORAGE_GET_F_CREATE);
6294
if (ptr)
6395
*ptr = 200;
6496

65-
ptr = bpf_cgrp_storage_get(&map_b, task->cgroups->dfl_cgrp, 0,
66-
BPF_LOCAL_STORAGE_GET_F_CREATE);
97+
ptr = bpf_cgrp_storage_get(&map_b, cgrp, 0, BPF_LOCAL_STORAGE_GET_F_CREATE);
6798
if (ptr)
6899
*ptr = 100;
100+
}
101+
102+
SEC("tp_btf/sys_enter")
103+
int BPF_PROG(on_enter, struct pt_regs *regs, long id)
104+
{
105+
struct task_struct *task = bpf_get_current_task_btf();
106+
struct cgroup *cgrp;
107+
108+
if (is_cgroup1) {
109+
cgrp = bpf_task_get_cgroup1(task, target_hid);
110+
if (!cgrp)
111+
return 0;
112+
113+
__on_enter(regs, id, cgrp);
114+
bpf_cgroup_release(cgrp);
115+
return 0;
116+
}
117+
118+
__on_enter(regs, id, task->cgroups->dfl_cgrp);
69119
return 0;
70120
}

tools/testing/selftests/bpf/progs/cgrp_ls_sleepable.c

+54-7
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,11 @@ struct {
1717

1818
__u32 target_pid;
1919
__u64 cgroup_id;
20+
int target_hid;
21+
bool is_cgroup1;
2022

23+
struct cgroup *bpf_task_get_cgroup1(struct task_struct *task, int hierarchy_id) __ksym;
24+
void bpf_cgroup_release(struct cgroup *cgrp) __ksym;
2125
void bpf_rcu_read_lock(void) __ksym;
2226
void bpf_rcu_read_unlock(void) __ksym;
2327

@@ -37,23 +41,50 @@ int cgroup_iter(struct bpf_iter__cgroup *ctx)
3741
return 0;
3842
}
3943

44+
static void __no_rcu_lock(struct cgroup *cgrp)
45+
{
46+
long *ptr;
47+
48+
/* Note that trace rcu is held in sleepable prog, so we can use
49+
* bpf_cgrp_storage_get() in sleepable prog.
50+
*/
51+
ptr = bpf_cgrp_storage_get(&map_a, cgrp, 0,
52+
BPF_LOCAL_STORAGE_GET_F_CREATE);
53+
if (ptr)
54+
cgroup_id = cgrp->kn->id;
55+
}
56+
4057
SEC("?fentry.s/" SYS_PREFIX "sys_getpgid")
41-
int no_rcu_lock(void *ctx)
58+
int cgrp1_no_rcu_lock(void *ctx)
4259
{
4360
struct task_struct *task;
4461
struct cgroup *cgrp;
45-
long *ptr;
62+
63+
task = bpf_get_current_task_btf();
64+
if (task->pid != target_pid)
65+
return 0;
66+
67+
/* bpf_task_get_cgroup1 can work in sleepable prog */
68+
cgrp = bpf_task_get_cgroup1(task, target_hid);
69+
if (!cgrp)
70+
return 0;
71+
72+
__no_rcu_lock(cgrp);
73+
bpf_cgroup_release(cgrp);
74+
return 0;
75+
}
76+
77+
SEC("?fentry.s/" SYS_PREFIX "sys_getpgid")
78+
int no_rcu_lock(void *ctx)
79+
{
80+
struct task_struct *task;
4681

4782
task = bpf_get_current_task_btf();
4883
if (task->pid != target_pid)
4984
return 0;
5085

5186
/* task->cgroups is untrusted in sleepable prog outside of RCU CS */
52-
cgrp = task->cgroups->dfl_cgrp;
53-
ptr = bpf_cgrp_storage_get(&map_a, cgrp, 0,
54-
BPF_LOCAL_STORAGE_GET_F_CREATE);
55-
if (ptr)
56-
cgroup_id = cgrp->kn->id;
87+
__no_rcu_lock(task->cgroups->dfl_cgrp);
5788
return 0;
5889
}
5990

@@ -68,6 +99,22 @@ int yes_rcu_lock(void *ctx)
6899
if (task->pid != target_pid)
69100
return 0;
70101

102+
if (is_cgroup1) {
103+
bpf_rcu_read_lock();
104+
cgrp = bpf_task_get_cgroup1(task, target_hid);
105+
if (!cgrp) {
106+
bpf_rcu_read_unlock();
107+
return 0;
108+
}
109+
110+
ptr = bpf_cgrp_storage_get(&map_a, cgrp, 0, BPF_LOCAL_STORAGE_GET_F_CREATE);
111+
if (ptr)
112+
cgroup_id = cgrp->kn->id;
113+
bpf_cgroup_release(cgrp);
114+
bpf_rcu_read_unlock();
115+
return 0;
116+
}
117+
71118
bpf_rcu_read_lock();
72119
cgrp = task->cgroups->dfl_cgrp;
73120
/* cgrp is trusted under RCU CS */

0 commit comments

Comments
 (0)