Skip to content

Commit a8250d1

Browse files
kkdwvdAlexei Starovoitov
authored andcommitted
selftests/bpf: Add a test for bpf_cgroup_from_id lookup in non-root cgns
Make sure that we only switch the cgroup namespace and enter a new cgroup in a child process separate from test_progs, to not mess up the environment for subsequent tests. To remove this cgroup, we need to wait for the child to exit, and then rmdir its cgroup. If the read call fails, or waitpid succeeds, we know the child exited (read call would fail when the last pipe end is closed, otherwise waitpid waits until exit(2) is called). We then invoke a newly introduced remove_cgroup_pid() helper, that identifies cgroup path using the passed in pid of the now dead child, instead of using the current process pid (getpid()). Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com> Link: https://lore.kernel.org/r/20250915032618.1551762-3-memxor@gmail.com Signed-off-by: Alexei Starovoitov <ast@kernel.org>
1 parent 2c89513 commit a8250d1

File tree

4 files changed

+104
-0
lines changed

4 files changed

+104
-0
lines changed

tools/testing/selftests/bpf/cgroup_helpers.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -412,6 +412,26 @@ void remove_cgroup(const char *relative_path)
412412
log_err("rmdiring cgroup %s .. %s", relative_path, cgroup_path);
413413
}
414414

415+
/*
416+
* remove_cgroup_pid() - Remove a cgroup setup by process identified by PID
417+
* @relative_path: The cgroup path, relative to the workdir, to remove
418+
* @pid: PID to be used to find cgroup_path
419+
*
420+
* This function expects a cgroup to already be created, relative to the cgroup
421+
* work dir. It also expects the cgroup doesn't have any children or live
422+
* processes and it removes the cgroup.
423+
*
424+
* On failure, it will print an error to stderr.
425+
*/
426+
void remove_cgroup_pid(const char *relative_path, int pid)
427+
{
428+
char cgroup_path[PATH_MAX + 1];
429+
430+
format_cgroup_path_pid(cgroup_path, relative_path, pid);
431+
if (rmdir(cgroup_path))
432+
log_err("rmdiring cgroup %s .. %s", relative_path, cgroup_path);
433+
}
434+
415435
/**
416436
* create_and_get_cgroup() - Create a cgroup, relative to workdir, and get the FD
417437
* @relative_path: The cgroup path, relative to the workdir, to join

tools/testing/selftests/bpf/cgroup_helpers.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ int cgroup_setup_and_join(const char *relative_path);
1919
int get_root_cgroup(void);
2020
int create_and_get_cgroup(const char *relative_path);
2121
void remove_cgroup(const char *relative_path);
22+
void remove_cgroup_pid(const char *relative_path, int pid);
2223
unsigned long long get_cgroup_id(const char *relative_path);
2324
int get_cgroup1_hierarchy_id(const char *subsys_name);
2425

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

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
#define _GNU_SOURCE
55
#include <cgroup_helpers.h>
66
#include <test_progs.h>
7+
#include <sched.h>
8+
#include <sys/wait.h>
79

810
#include "cgrp_kfunc_failure.skel.h"
911
#include "cgrp_kfunc_success.skel.h"
@@ -87,6 +89,72 @@ static const char * const success_tests[] = {
8789
"test_cgrp_from_id",
8890
};
8991

92+
static void test_cgrp_from_id_ns(void)
93+
{
94+
LIBBPF_OPTS(bpf_test_run_opts, opts);
95+
struct cgrp_kfunc_success *skel;
96+
struct bpf_program *prog;
97+
int pid, pipe_fd[2];
98+
99+
skel = open_load_cgrp_kfunc_skel();
100+
if (!ASSERT_OK_PTR(skel, "open_load_skel"))
101+
return;
102+
103+
if (!ASSERT_OK(skel->bss->err, "pre_mkdir_err"))
104+
goto cleanup;
105+
106+
prog = skel->progs.test_cgrp_from_id_ns;
107+
108+
if (!ASSERT_OK(pipe(pipe_fd), "pipe"))
109+
goto cleanup;
110+
111+
pid = fork();
112+
if (!ASSERT_GE(pid, 0, "fork result")) {
113+
close(pipe_fd[0]);
114+
close(pipe_fd[1]);
115+
goto cleanup;
116+
}
117+
118+
if (pid == 0) {
119+
int ret = 0;
120+
121+
close(pipe_fd[0]);
122+
123+
if (!ASSERT_GE(cgroup_setup_and_join("cgrp_from_id_ns"), 0, "join cgroup"))
124+
exit(1);
125+
126+
if (!ASSERT_OK(unshare(CLONE_NEWCGROUP), "unshare cgns"))
127+
exit(1);
128+
129+
ret = bpf_prog_test_run_opts(bpf_program__fd(prog), &opts);
130+
if (!ASSERT_OK(ret, "test run ret"))
131+
exit(1);
132+
133+
if (!ASSERT_OK(opts.retval, "test run retval"))
134+
exit(1);
135+
136+
if (!ASSERT_EQ(write(pipe_fd[1], &ret, sizeof(ret)), sizeof(ret), "write pipe"))
137+
exit(1);
138+
139+
exit(0);
140+
} else {
141+
int res;
142+
143+
close(pipe_fd[1]);
144+
145+
ASSERT_EQ(read(pipe_fd[0], &res, sizeof(res)), sizeof(res), "read res");
146+
ASSERT_EQ(waitpid(pid, NULL, 0), pid, "wait on child");
147+
148+
remove_cgroup_pid("cgrp_from_id_ns", pid);
149+
150+
ASSERT_OK(res, "result from run");
151+
}
152+
153+
close(pipe_fd[0]);
154+
cleanup:
155+
cgrp_kfunc_success__destroy(skel);
156+
}
157+
90158
void test_cgrp_kfunc(void)
91159
{
92160
int i, err;
@@ -102,6 +170,9 @@ void test_cgrp_kfunc(void)
102170
run_success_test(success_tests[i]);
103171
}
104172

173+
if (test__start_subtest("test_cgrp_from_id_ns"))
174+
test_cgrp_from_id_ns();
175+
105176
RUN_TESTS(cgrp_kfunc_failure);
106177

107178
cleanup:

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,3 +221,15 @@ int BPF_PROG(test_cgrp_from_id, struct cgroup *cgrp, const char *path)
221221

222222
return 0;
223223
}
224+
225+
SEC("syscall")
226+
int test_cgrp_from_id_ns(void *ctx)
227+
{
228+
struct cgroup *cg;
229+
230+
cg = bpf_cgroup_from_id(1);
231+
if (!cg)
232+
return 42;
233+
bpf_cgroup_release(cg);
234+
return 0;
235+
}

0 commit comments

Comments
 (0)