xref: /linux/tools/testing/selftests/bpf/progs/cgrp_kfunc_success.c (revision bfcb94aacc92f7025bd86a545037e5eb8db00e32)
1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (c) 2022 Meta Platforms, Inc. and affiliates. */
3 
4 #include <vmlinux.h>
5 #include <bpf/bpf_tracing.h>
6 #include <bpf/bpf_helpers.h>
7 
8 #include "cgrp_kfunc_common.h"
9 
10 char _license[] SEC("license") = "GPL";
11 
12 int err, pid, invocations;
13 
14 /* Prototype for all of the program trace events below:
15  *
16  * TRACE_EVENT(cgroup_mkdir,
17  *         TP_PROTO(struct cgroup *cgrp, const char *path),
18  *         TP_ARGS(cgrp, path)
19  */
20 
21 static bool is_test_kfunc_task(void)
22 {
23 	int cur_pid = bpf_get_current_pid_tgid() >> 32;
24 	bool same = pid == cur_pid;
25 
26 	if (same)
27 		__sync_fetch_and_add(&invocations, 1);
28 
29 	return same;
30 }
31 
32 SEC("tp_btf/cgroup_mkdir")
33 int BPF_PROG(test_cgrp_acquire_release_argument, struct cgroup *cgrp, const char *path)
34 {
35 	struct cgroup *acquired;
36 
37 	if (!is_test_kfunc_task())
38 		return 0;
39 
40 	acquired = bpf_cgroup_acquire(cgrp);
41 	bpf_cgroup_release(acquired);
42 
43 	return 0;
44 }
45 
46 SEC("tp_btf/cgroup_mkdir")
47 int BPF_PROG(test_cgrp_acquire_leave_in_map, struct cgroup *cgrp, const char *path)
48 {
49 	long status;
50 
51 	if (!is_test_kfunc_task())
52 		return 0;
53 
54 	status = cgrps_kfunc_map_insert(cgrp);
55 	if (status)
56 		err = 1;
57 
58 	return 0;
59 }
60 
61 SEC("tp_btf/cgroup_mkdir")
62 int BPF_PROG(test_cgrp_xchg_release, struct cgroup *cgrp, const char *path)
63 {
64 	struct cgroup *kptr, *cg;
65 	struct __cgrps_kfunc_map_value *v;
66 	long status;
67 
68 	if (!is_test_kfunc_task())
69 		return 0;
70 
71 	status = cgrps_kfunc_map_insert(cgrp);
72 	if (status) {
73 		err = 1;
74 		return 0;
75 	}
76 
77 	v = cgrps_kfunc_map_value_lookup(cgrp);
78 	if (!v) {
79 		err = 2;
80 		return 0;
81 	}
82 
83 	kptr = v->cgrp;
84 	if (!kptr) {
85 		err = 4;
86 		return 0;
87 	}
88 
89 	cg = bpf_cgroup_ancestor(kptr, 1);
90 	if (cg)	/* verifier only check */
91 		bpf_cgroup_release(cg);
92 
93 	kptr = bpf_kptr_xchg(&v->cgrp, NULL);
94 	if (!kptr) {
95 		err = 3;
96 		return 0;
97 	}
98 
99 	bpf_cgroup_release(kptr);
100 
101 	return 0;
102 }
103 
104 SEC("tp_btf/cgroup_mkdir")
105 int BPF_PROG(test_cgrp_get_release, struct cgroup *cgrp, const char *path)
106 {
107 	struct cgroup *kptr;
108 	struct __cgrps_kfunc_map_value *v;
109 	long status;
110 
111 	if (!is_test_kfunc_task())
112 		return 0;
113 
114 	status = cgrps_kfunc_map_insert(cgrp);
115 	if (status) {
116 		err = 1;
117 		return 0;
118 	}
119 
120 	v = cgrps_kfunc_map_value_lookup(cgrp);
121 	if (!v) {
122 		err = 2;
123 		return 0;
124 	}
125 
126 	kptr = bpf_cgroup_kptr_get(&v->cgrp);
127 	if (!kptr) {
128 		err = 3;
129 		return 0;
130 	}
131 
132 	bpf_cgroup_release(kptr);
133 
134 	return 0;
135 }
136 
137 SEC("tp_btf/cgroup_mkdir")
138 int BPF_PROG(test_cgrp_get_ancestors, struct cgroup *cgrp, const char *path)
139 {
140 	struct cgroup *self, *ancestor1, *invalid;
141 
142 	if (!is_test_kfunc_task())
143 		return 0;
144 
145 	self = bpf_cgroup_ancestor(cgrp, cgrp->level);
146 	if (!self) {
147 		err = 1;
148 		return 0;
149 	}
150 
151 	if (self->self.id != cgrp->self.id) {
152 		bpf_cgroup_release(self);
153 		err = 2;
154 		return 0;
155 	}
156 	bpf_cgroup_release(self);
157 
158 	ancestor1 = bpf_cgroup_ancestor(cgrp, cgrp->level - 1);
159 	if (!ancestor1) {
160 		err = 3;
161 		return 0;
162 	}
163 	bpf_cgroup_release(ancestor1);
164 
165 	invalid = bpf_cgroup_ancestor(cgrp, 10000);
166 	if (invalid) {
167 		bpf_cgroup_release(invalid);
168 		err = 4;
169 		return 0;
170 	}
171 
172 	invalid = bpf_cgroup_ancestor(cgrp, -1);
173 	if (invalid) {
174 		bpf_cgroup_release(invalid);
175 		err = 5;
176 		return 0;
177 	}
178 
179 	return 0;
180 }
181 
182 SEC("tp_btf/cgroup_mkdir")
183 int BPF_PROG(test_cgrp_from_id, struct cgroup *cgrp, const char *path)
184 {
185 	struct cgroup *parent, *res;
186 	u64 parent_cgid;
187 
188 	if (!is_test_kfunc_task())
189 		return 0;
190 
191 	/* @cgrp's ID is not visible yet, let's test with the parent */
192 	parent = bpf_cgroup_ancestor(cgrp, cgrp->level - 1);
193 	if (!parent) {
194 		err = 1;
195 		return 0;
196 	}
197 
198 	parent_cgid = parent->kn->id;
199 	bpf_cgroup_release(parent);
200 
201 	res = bpf_cgroup_from_id(parent_cgid);
202 	if (!res) {
203 		err = 2;
204 		return 0;
205 	}
206 
207 	bpf_cgroup_release(res);
208 
209 	if (res != parent) {
210 		err = 3;
211 		return 0;
212 	}
213 
214 	res = bpf_cgroup_from_id((u64)-1);
215 	if (res) {
216 		bpf_cgroup_release(res);
217 		err = 4;
218 		return 0;
219 	}
220 
221 	return 0;
222 }
223