xref: /linux/tools/testing/selftests/bpf/prog_tests/cgrp_kfunc.c (revision ae28ed4578e6d5a481e39c5a9827f27048661fdd)
1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (c) 2022 Meta Platforms, Inc. and affiliates. */
3 
4 #define _GNU_SOURCE
5 #include <cgroup_helpers.h>
6 #include <test_progs.h>
7 #include <sched.h>
8 #include <sys/wait.h>
9 
10 #include "cgrp_kfunc_failure.skel.h"
11 #include "cgrp_kfunc_success.skel.h"
12 
13 static struct cgrp_kfunc_success *open_load_cgrp_kfunc_skel(void)
14 {
15 	struct cgrp_kfunc_success *skel;
16 	int err;
17 
18 	skel = cgrp_kfunc_success__open();
19 	if (!ASSERT_OK_PTR(skel, "skel_open"))
20 		return NULL;
21 
22 	skel->bss->pid = getpid();
23 
24 	err = cgrp_kfunc_success__load(skel);
25 	if (!ASSERT_OK(err, "skel_load"))
26 		goto cleanup;
27 
28 	return skel;
29 
30 cleanup:
31 	cgrp_kfunc_success__destroy(skel);
32 	return NULL;
33 }
34 
35 static int mkdir_rm_test_dir(void)
36 {
37 	int fd;
38 	const char *cgrp_path = "cgrp_kfunc";
39 
40 	fd = create_and_get_cgroup(cgrp_path);
41 	if (!ASSERT_GT(fd, 0, "mkdir_cgrp_fd"))
42 		return -1;
43 
44 	close(fd);
45 	remove_cgroup(cgrp_path);
46 
47 	return 0;
48 }
49 
50 static void run_success_test(const char *prog_name)
51 {
52 	struct cgrp_kfunc_success *skel;
53 	struct bpf_program *prog;
54 	struct bpf_link *link = NULL;
55 
56 	skel = open_load_cgrp_kfunc_skel();
57 	if (!ASSERT_OK_PTR(skel, "open_load_skel"))
58 		return;
59 
60 	if (!ASSERT_OK(skel->bss->err, "pre_mkdir_err"))
61 		goto cleanup;
62 
63 	prog = bpf_object__find_program_by_name(skel->obj, prog_name);
64 	if (!ASSERT_OK_PTR(prog, "bpf_object__find_program_by_name"))
65 		goto cleanup;
66 
67 	link = bpf_program__attach(prog);
68 	if (!ASSERT_OK_PTR(link, "attached_link"))
69 		goto cleanup;
70 
71 	ASSERT_EQ(skel->bss->invocations, 0, "pre_rmdir_count");
72 	if (!ASSERT_OK(mkdir_rm_test_dir(), "cgrp_mkdir"))
73 		goto cleanup;
74 
75 	ASSERT_EQ(skel->bss->invocations, 1, "post_rmdir_count");
76 	ASSERT_OK(skel->bss->err, "post_rmdir_err");
77 
78 cleanup:
79 	bpf_link__destroy(link);
80 	cgrp_kfunc_success__destroy(skel);
81 }
82 
83 static const char * const success_tests[] = {
84 	"test_cgrp_acquire_release_argument",
85 	"test_cgrp_acquire_leave_in_map",
86 	"test_cgrp_xchg_release",
87 	"test_cgrp_get_release",
88 	"test_cgrp_get_ancestors",
89 	"test_cgrp_from_id",
90 };
91 
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 
158 void test_cgrp_kfunc(void)
159 {
160 	int i, err;
161 
162 	err = setup_cgroup_environment();
163 	if (!ASSERT_OK(err, "cgrp_env_setup"))
164 		goto cleanup;
165 
166 	for (i = 0; i < ARRAY_SIZE(success_tests); i++) {
167 		if (!test__start_subtest(success_tests[i]))
168 			continue;
169 
170 		run_success_test(success_tests[i]);
171 	}
172 
173 	if (test__start_subtest("test_cgrp_from_id_ns"))
174 		test_cgrp_from_id_ns();
175 
176 	RUN_TESTS(cgrp_kfunc_failure);
177 
178 cleanup:
179 	cleanup_cgroup_environment();
180 }
181