Skip to content

Commit 41d76c7

Browse files
yonghong-songAlexei Starovoitov
authored andcommitted
bpf: Add sleepable prog tests for cgrp local storage
Add three tests for cgrp local storage support for sleepable progs. Two tests can load and run properly, one for cgroup_iter, another for passing current->cgroups->dfl_cgrp to bpf_cgrp_storage_get() helper. One test has bpf_rcu_read_lock() and failed to load. Signed-off-by: Yonghong Song <yhs@fb.com> Link: https://lore.kernel.org/r/20221201050449.2785613-1-yhs@fb.com Signed-off-by: Alexei Starovoitov <ast@kernel.org>
1 parent 2c40d97 commit 41d76c7

File tree

2 files changed

+174
-0
lines changed

2 files changed

+174
-0
lines changed

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

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@
1010
#include "cgrp_ls_recursion.skel.h"
1111
#include "cgrp_ls_attach_cgroup.skel.h"
1212
#include "cgrp_ls_negative.skel.h"
13+
#include "cgrp_ls_sleepable.skel.h"
1314
#include "network_helpers.h"
15+
#include "cgroup_helpers.h"
1416

1517
struct socket_cookie {
1618
__u64 cookie_key;
@@ -150,14 +152,100 @@ static void test_negative(void)
150152
}
151153
}
152154

155+
static void test_cgroup_iter_sleepable(int cgroup_fd, __u64 cgroup_id)
156+
{
157+
DECLARE_LIBBPF_OPTS(bpf_iter_attach_opts, opts);
158+
union bpf_iter_link_info linfo;
159+
struct cgrp_ls_sleepable *skel;
160+
struct bpf_link *link;
161+
int err, iter_fd;
162+
char buf[16];
163+
164+
skel = cgrp_ls_sleepable__open();
165+
if (!ASSERT_OK_PTR(skel, "skel_open"))
166+
return;
167+
168+
bpf_program__set_autoload(skel->progs.cgroup_iter, true);
169+
err = cgrp_ls_sleepable__load(skel);
170+
if (!ASSERT_OK(err, "skel_load"))
171+
goto out;
172+
173+
memset(&linfo, 0, sizeof(linfo));
174+
linfo.cgroup.cgroup_fd = cgroup_fd;
175+
linfo.cgroup.order = BPF_CGROUP_ITER_SELF_ONLY;
176+
opts.link_info = &linfo;
177+
opts.link_info_len = sizeof(linfo);
178+
link = bpf_program__attach_iter(skel->progs.cgroup_iter, &opts);
179+
if (!ASSERT_OK_PTR(link, "attach_iter"))
180+
goto out;
181+
182+
iter_fd = bpf_iter_create(bpf_link__fd(link));
183+
if (!ASSERT_GE(iter_fd, 0, "iter_create"))
184+
goto out;
185+
186+
/* trigger the program run */
187+
(void)read(iter_fd, buf, sizeof(buf));
188+
189+
ASSERT_EQ(skel->bss->cgroup_id, cgroup_id, "cgroup_id");
190+
191+
close(iter_fd);
192+
out:
193+
cgrp_ls_sleepable__destroy(skel);
194+
}
195+
196+
static void test_no_rcu_lock(__u64 cgroup_id)
197+
{
198+
struct cgrp_ls_sleepable *skel;
199+
int err;
200+
201+
skel = cgrp_ls_sleepable__open();
202+
if (!ASSERT_OK_PTR(skel, "skel_open"))
203+
return;
204+
205+
skel->bss->target_pid = syscall(SYS_gettid);
206+
207+
bpf_program__set_autoload(skel->progs.no_rcu_lock, true);
208+
err = cgrp_ls_sleepable__load(skel);
209+
if (!ASSERT_OK(err, "skel_load"))
210+
goto out;
211+
212+
err = cgrp_ls_sleepable__attach(skel);
213+
if (!ASSERT_OK(err, "skel_attach"))
214+
goto out;
215+
216+
syscall(SYS_getpgid);
217+
218+
ASSERT_EQ(skel->bss->cgroup_id, cgroup_id, "cgroup_id");
219+
out:
220+
cgrp_ls_sleepable__destroy(skel);
221+
}
222+
223+
static void test_rcu_lock(void)
224+
{
225+
struct cgrp_ls_sleepable *skel;
226+
int err;
227+
228+
skel = cgrp_ls_sleepable__open();
229+
if (!ASSERT_OK_PTR(skel, "skel_open"))
230+
return;
231+
232+
bpf_program__set_autoload(skel->progs.yes_rcu_lock, true);
233+
err = cgrp_ls_sleepable__load(skel);
234+
ASSERT_ERR(err, "skel_load");
235+
236+
cgrp_ls_sleepable__destroy(skel);
237+
}
238+
153239
void test_cgrp_local_storage(void)
154240
{
241+
__u64 cgroup_id;
155242
int cgroup_fd;
156243

157244
cgroup_fd = test__join_cgroup("/cgrp_local_storage");
158245
if (!ASSERT_GE(cgroup_fd, 0, "join_cgroup /cgrp_local_storage"))
159246
return;
160247

248+
cgroup_id = get_cgroup_id("/cgrp_local_storage");
161249
if (test__start_subtest("tp_btf"))
162250
test_tp_btf(cgroup_fd);
163251
if (test__start_subtest("attach_cgroup"))
@@ -166,6 +254,12 @@ void test_cgrp_local_storage(void)
166254
test_recursion(cgroup_fd);
167255
if (test__start_subtest("negative"))
168256
test_negative();
257+
if (test__start_subtest("cgroup_iter_sleepable"))
258+
test_cgroup_iter_sleepable(cgroup_fd, cgroup_id);
259+
if (test__start_subtest("no_rcu_lock"))
260+
test_no_rcu_lock(cgroup_id);
261+
if (test__start_subtest("rcu_lock"))
262+
test_rcu_lock();
169263

170264
close(cgroup_fd);
171265
}
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
/* Copyright (c) 2022 Meta Platforms, Inc. and affiliates. */
3+
4+
#include "bpf_iter.h"
5+
#include <bpf/bpf_helpers.h>
6+
#include <bpf/bpf_tracing.h>
7+
#include "bpf_misc.h"
8+
9+
char _license[] SEC("license") = "GPL";
10+
11+
struct {
12+
__uint(type, BPF_MAP_TYPE_CGRP_STORAGE);
13+
__uint(map_flags, BPF_F_NO_PREALLOC);
14+
__type(key, int);
15+
__type(value, long);
16+
} map_a SEC(".maps");
17+
18+
__u32 target_pid;
19+
__u64 cgroup_id;
20+
21+
void bpf_rcu_read_lock(void) __ksym;
22+
void bpf_rcu_read_unlock(void) __ksym;
23+
24+
SEC("?iter.s/cgroup")
25+
int cgroup_iter(struct bpf_iter__cgroup *ctx)
26+
{
27+
struct seq_file *seq = ctx->meta->seq;
28+
struct cgroup *cgrp = ctx->cgroup;
29+
long *ptr;
30+
31+
if (cgrp == NULL)
32+
return 0;
33+
34+
ptr = bpf_cgrp_storage_get(&map_a, cgrp, 0,
35+
BPF_LOCAL_STORAGE_GET_F_CREATE);
36+
if (ptr)
37+
cgroup_id = cgrp->kn->id;
38+
return 0;
39+
}
40+
41+
SEC("?fentry.s/" SYS_PREFIX "sys_getpgid")
42+
int no_rcu_lock(void *ctx)
43+
{
44+
struct task_struct *task;
45+
struct cgroup *cgrp;
46+
long *ptr;
47+
48+
task = bpf_get_current_task_btf();
49+
if (task->pid != target_pid)
50+
return 0;
51+
52+
/* ptr_to_btf_id semantics. should work. */
53+
cgrp = task->cgroups->dfl_cgrp;
54+
ptr = bpf_cgrp_storage_get(&map_a, cgrp, 0,
55+
BPF_LOCAL_STORAGE_GET_F_CREATE);
56+
if (ptr)
57+
cgroup_id = cgrp->kn->id;
58+
return 0;
59+
}
60+
61+
SEC("?fentry.s/" SYS_PREFIX "sys_getpgid")
62+
int yes_rcu_lock(void *ctx)
63+
{
64+
struct task_struct *task;
65+
struct cgroup *cgrp;
66+
long *ptr;
67+
68+
task = bpf_get_current_task_btf();
69+
if (task->pid != target_pid)
70+
return 0;
71+
72+
bpf_rcu_read_lock();
73+
cgrp = task->cgroups->dfl_cgrp;
74+
/* cgrp is untrusted and cannot pass to bpf_cgrp_storage_get() helper. */
75+
ptr = bpf_cgrp_storage_get(&map_a, cgrp, 0, BPF_LOCAL_STORAGE_GET_F_CREATE);
76+
if (ptr)
77+
cgroup_id = cgrp->kn->id;
78+
bpf_rcu_read_unlock();
79+
return 0;
80+
}

0 commit comments

Comments
 (0)