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 /* Prototype for all of the program trace events below:
13  *
14  * TRACE_EVENT(cgroup_mkdir,
15  *         TP_PROTO(struct cgroup *cgrp, const char *path),
16  *         TP_ARGS(cgrp, path)
17  */
18 
19 static struct __cgrps_kfunc_map_value *insert_lookup_cgrp(struct cgroup *cgrp)
20 {
21 	int status;
22 
23 	status = cgrps_kfunc_map_insert(cgrp);
24 	if (status)
25 		return NULL;
26 
27 	return cgrps_kfunc_map_value_lookup(cgrp);
28 }
29 
30 SEC("tp_btf/cgroup_mkdir")
31 int BPF_PROG(cgrp_kfunc_acquire_untrusted, struct cgroup *cgrp, const char *path)
32 {
33 	struct cgroup *acquired;
34 	struct __cgrps_kfunc_map_value *v;
35 
36 	v = insert_lookup_cgrp(cgrp);
37 	if (!v)
38 		return 0;
39 
40 	/* Can't invoke bpf_cgroup_acquire() on an untrusted pointer. */
41 	acquired = bpf_cgroup_acquire(v->cgrp);
42 	bpf_cgroup_release(acquired);
43 
44 	return 0;
45 }
46 
47 SEC("tp_btf/cgroup_mkdir")
48 int BPF_PROG(cgrp_kfunc_acquire_fp, struct cgroup *cgrp, const char *path)
49 {
50 	struct cgroup *acquired, *stack_cgrp = (struct cgroup *)&path;
51 
52 	/* Can't invoke bpf_cgroup_acquire() on a random frame pointer. */
53 	acquired = bpf_cgroup_acquire((struct cgroup *)&stack_cgrp);
54 	bpf_cgroup_release(acquired);
55 
56 	return 0;
57 }
58 
59 SEC("kretprobe/cgroup_destroy_locked")
60 int BPF_PROG(cgrp_kfunc_acquire_unsafe_kretprobe, struct cgroup *cgrp)
61 {
62 	struct cgroup *acquired;
63 
64 	/* Can't acquire an untrusted struct cgroup * pointer. */
65 	acquired = bpf_cgroup_acquire(cgrp);
66 	bpf_cgroup_release(acquired);
67 
68 	return 0;
69 }
70 
71 SEC("tp_btf/cgroup_mkdir")
72 int BPF_PROG(cgrp_kfunc_acquire_trusted_walked, struct cgroup *cgrp, const char *path)
73 {
74 	struct cgroup *acquired;
75 
76 	/* Can't invoke bpf_cgroup_acquire() on a pointer obtained from walking a trusted cgroup. */
77 	acquired = bpf_cgroup_acquire(cgrp->old_dom_cgrp);
78 	bpf_cgroup_release(acquired);
79 
80 	return 0;
81 }
82 
83 
84 SEC("tp_btf/cgroup_mkdir")
85 int BPF_PROG(cgrp_kfunc_acquire_null, struct cgroup *cgrp, const char *path)
86 {
87 	struct cgroup *acquired;
88 
89 	/* Can't invoke bpf_cgroup_acquire() on a NULL pointer. */
90 	acquired = bpf_cgroup_acquire(NULL);
91 	if (!acquired)
92 		return 0;
93 	bpf_cgroup_release(acquired);
94 
95 	return 0;
96 }
97 
98 SEC("tp_btf/cgroup_mkdir")
99 int BPF_PROG(cgrp_kfunc_acquire_unreleased, struct cgroup *cgrp, const char *path)
100 {
101 	struct cgroup *acquired;
102 
103 	acquired = bpf_cgroup_acquire(cgrp);
104 
105 	/* Acquired cgroup is never released. */
106 
107 	return 0;
108 }
109 
110 SEC("tp_btf/cgroup_mkdir")
111 int BPF_PROG(cgrp_kfunc_get_non_kptr_param, struct cgroup *cgrp, const char *path)
112 {
113 	struct cgroup *kptr;
114 
115 	/* Cannot use bpf_cgroup_kptr_get() on a non-kptr, even on a valid cgroup. */
116 	kptr = bpf_cgroup_kptr_get(&cgrp);
117 	if (!kptr)
118 		return 0;
119 
120 	bpf_cgroup_release(kptr);
121 
122 	return 0;
123 }
124 
125 SEC("tp_btf/cgroup_mkdir")
126 int BPF_PROG(cgrp_kfunc_get_non_kptr_acquired, struct cgroup *cgrp, const char *path)
127 {
128 	struct cgroup *kptr, *acquired;
129 
130 	acquired = bpf_cgroup_acquire(cgrp);
131 
132 	/* Cannot use bpf_cgroup_kptr_get() on a non-map-value, even if the kptr was acquired. */
133 	kptr = bpf_cgroup_kptr_get(&acquired);
134 	bpf_cgroup_release(acquired);
135 	if (!kptr)
136 		return 0;
137 
138 	bpf_cgroup_release(kptr);
139 
140 	return 0;
141 }
142 
143 SEC("tp_btf/cgroup_mkdir")
144 int BPF_PROG(cgrp_kfunc_get_null, struct cgroup *cgrp, const char *path)
145 {
146 	struct cgroup *kptr;
147 
148 	/* Cannot use bpf_cgroup_kptr_get() on a NULL pointer. */
149 	kptr = bpf_cgroup_kptr_get(NULL);
150 	if (!kptr)
151 		return 0;
152 
153 	bpf_cgroup_release(kptr);
154 
155 	return 0;
156 }
157 
158 SEC("tp_btf/cgroup_mkdir")
159 int BPF_PROG(cgrp_kfunc_xchg_unreleased, struct cgroup *cgrp, const char *path)
160 {
161 	struct cgroup *kptr;
162 	struct __cgrps_kfunc_map_value *v;
163 
164 	v = insert_lookup_cgrp(cgrp);
165 	if (!v)
166 		return 0;
167 
168 	kptr = bpf_kptr_xchg(&v->cgrp, NULL);
169 	if (!kptr)
170 		return 0;
171 
172 	/* Kptr retrieved from map is never released. */
173 
174 	return 0;
175 }
176 
177 SEC("tp_btf/cgroup_mkdir")
178 int BPF_PROG(cgrp_kfunc_get_unreleased, struct cgroup *cgrp, const char *path)
179 {
180 	struct cgroup *kptr;
181 	struct __cgrps_kfunc_map_value *v;
182 
183 	v = insert_lookup_cgrp(cgrp);
184 	if (!v)
185 		return 0;
186 
187 	kptr = bpf_cgroup_kptr_get(&v->cgrp);
188 	if (!kptr)
189 		return 0;
190 
191 	/* Kptr acquired above is never released. */
192 
193 	return 0;
194 }
195 
196 SEC("tp_btf/cgroup_mkdir")
197 int BPF_PROG(cgrp_kfunc_release_untrusted, struct cgroup *cgrp, const char *path)
198 {
199 	struct __cgrps_kfunc_map_value *v;
200 
201 	v = insert_lookup_cgrp(cgrp);
202 	if (!v)
203 		return 0;
204 
205 	/* Can't invoke bpf_cgroup_release() on an untrusted pointer. */
206 	bpf_cgroup_release(v->cgrp);
207 
208 	return 0;
209 }
210 
211 SEC("tp_btf/cgroup_mkdir")
212 int BPF_PROG(cgrp_kfunc_release_fp, struct cgroup *cgrp, const char *path)
213 {
214 	struct cgroup *acquired = (struct cgroup *)&path;
215 
216 	/* Cannot release random frame pointer. */
217 	bpf_cgroup_release(acquired);
218 
219 	return 0;
220 }
221 
222 SEC("tp_btf/cgroup_mkdir")
223 int BPF_PROG(cgrp_kfunc_release_null, struct cgroup *cgrp, const char *path)
224 {
225 	struct __cgrps_kfunc_map_value local, *v;
226 	long status;
227 	struct cgroup *acquired, *old;
228 	s32 id;
229 
230 	status = bpf_probe_read_kernel(&id, sizeof(id), &cgrp->self.id);
231 	if (status)
232 		return 0;
233 
234 	local.cgrp = NULL;
235 	status = bpf_map_update_elem(&__cgrps_kfunc_map, &id, &local, BPF_NOEXIST);
236 	if (status)
237 		return status;
238 
239 	v = bpf_map_lookup_elem(&__cgrps_kfunc_map, &id);
240 	if (!v)
241 		return -ENOENT;
242 
243 	acquired = bpf_cgroup_acquire(cgrp);
244 
245 	old = bpf_kptr_xchg(&v->cgrp, acquired);
246 
247 	/* old cannot be passed to bpf_cgroup_release() without a NULL check. */
248 	bpf_cgroup_release(old);
249 
250 	return 0;
251 }
252 
253 SEC("tp_btf/cgroup_mkdir")
254 int BPF_PROG(cgrp_kfunc_release_unacquired, struct cgroup *cgrp, const char *path)
255 {
256 	/* Cannot release trusted cgroup pointer which was not acquired. */
257 	bpf_cgroup_release(cgrp);
258 
259 	return 0;
260 }
261