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 "bpf_misc.h"
9 #include "task_kfunc_common.h"
10 
11 char _license[] SEC("license") = "GPL";
12 
13 /* Prototype for all of the program trace events below:
14  *
15  * TRACE_EVENT(task_newtask,
16  *         TP_PROTO(struct task_struct *p, u64 clone_flags)
17  */
18 
19 static struct __tasks_kfunc_map_value *insert_lookup_task(struct task_struct *task)
20 {
21 	int status;
22 
23 	status = tasks_kfunc_map_insert(task);
24 	if (status)
25 		return NULL;
26 
27 	return tasks_kfunc_map_value_lookup(task);
28 }
29 
30 SEC("tp_btf/task_newtask")
31 __failure __msg("Possibly NULL pointer passed to trusted arg0")
32 int BPF_PROG(task_kfunc_acquire_untrusted, struct task_struct *task, u64 clone_flags)
33 {
34 	struct task_struct *acquired;
35 	struct __tasks_kfunc_map_value *v;
36 
37 	v = insert_lookup_task(task);
38 	if (!v)
39 		return 0;
40 
41 	/* Can't invoke bpf_task_acquire() on an untrusted pointer. */
42 	acquired = bpf_task_acquire(v->task);
43 	bpf_task_release(acquired);
44 
45 	return 0;
46 }
47 
48 SEC("tp_btf/task_newtask")
49 __failure __msg("arg#0 pointer type STRUCT task_struct must point")
50 int BPF_PROG(task_kfunc_acquire_fp, struct task_struct *task, u64 clone_flags)
51 {
52 	struct task_struct *acquired, *stack_task = (struct task_struct *)&clone_flags;
53 
54 	/* Can't invoke bpf_task_acquire() on a random frame pointer. */
55 	acquired = bpf_task_acquire((struct task_struct *)&stack_task);
56 	bpf_task_release(acquired);
57 
58 	return 0;
59 }
60 
61 SEC("kretprobe/free_task")
62 __failure __msg("reg type unsupported for arg#0 function")
63 int BPF_PROG(task_kfunc_acquire_unsafe_kretprobe, struct task_struct *task, u64 clone_flags)
64 {
65 	struct task_struct *acquired;
66 
67 	acquired = bpf_task_acquire(task);
68 	/* Can't release a bpf_task_acquire()'d task without a NULL check. */
69 	bpf_task_release(acquired);
70 
71 	return 0;
72 }
73 
74 SEC("tp_btf/task_newtask")
75 __failure __msg("R1 must be referenced or trusted")
76 int BPF_PROG(task_kfunc_acquire_trusted_walked, struct task_struct *task, u64 clone_flags)
77 {
78 	struct task_struct *acquired;
79 
80 	/* Can't invoke bpf_task_acquire() on a trusted pointer obtained from walking a struct. */
81 	acquired = bpf_task_acquire(task->group_leader);
82 	bpf_task_release(acquired);
83 
84 	return 0;
85 }
86 
87 
88 SEC("tp_btf/task_newtask")
89 __failure __msg("Possibly NULL pointer passed to trusted arg0")
90 int BPF_PROG(task_kfunc_acquire_null, struct task_struct *task, u64 clone_flags)
91 {
92 	struct task_struct *acquired;
93 
94 	/* Can't invoke bpf_task_acquire() on a NULL pointer. */
95 	acquired = bpf_task_acquire(NULL);
96 	if (!acquired)
97 		return 0;
98 	bpf_task_release(acquired);
99 
100 	return 0;
101 }
102 
103 SEC("tp_btf/task_newtask")
104 __failure __msg("Unreleased reference")
105 int BPF_PROG(task_kfunc_acquire_unreleased, struct task_struct *task, u64 clone_flags)
106 {
107 	struct task_struct *acquired;
108 
109 	acquired = bpf_task_acquire(task);
110 
111 	/* Acquired task is never released. */
112 
113 	return 0;
114 }
115 
116 SEC("tp_btf/task_newtask")
117 __failure __msg("arg#0 expected pointer to map value")
118 int BPF_PROG(task_kfunc_get_non_kptr_param, struct task_struct *task, u64 clone_flags)
119 {
120 	struct task_struct *kptr;
121 
122 	/* Cannot use bpf_task_kptr_get() on a non-kptr, even on a valid task. */
123 	kptr = bpf_task_kptr_get(&task);
124 	if (!kptr)
125 		return 0;
126 
127 	bpf_task_release(kptr);
128 
129 	return 0;
130 }
131 
132 SEC("tp_btf/task_newtask")
133 __failure __msg("arg#0 expected pointer to map value")
134 int BPF_PROG(task_kfunc_get_non_kptr_acquired, struct task_struct *task, u64 clone_flags)
135 {
136 	struct task_struct *kptr, *acquired;
137 
138 	acquired = bpf_task_acquire(task);
139 
140 	/* Cannot use bpf_task_kptr_get() on a non-kptr, even if it was acquired. */
141 	kptr = bpf_task_kptr_get(&acquired);
142 	bpf_task_release(acquired);
143 	if (!kptr)
144 		return 0;
145 
146 	bpf_task_release(kptr);
147 
148 	return 0;
149 }
150 
151 SEC("tp_btf/task_newtask")
152 __failure __msg("arg#0 expected pointer to map value")
153 int BPF_PROG(task_kfunc_get_null, struct task_struct *task, u64 clone_flags)
154 {
155 	struct task_struct *kptr;
156 
157 	/* Cannot use bpf_task_kptr_get() on a NULL pointer. */
158 	kptr = bpf_task_kptr_get(NULL);
159 	if (!kptr)
160 		return 0;
161 
162 	bpf_task_release(kptr);
163 
164 	return 0;
165 }
166 
167 SEC("tp_btf/task_newtask")
168 __failure __msg("Unreleased reference")
169 int BPF_PROG(task_kfunc_xchg_unreleased, struct task_struct *task, u64 clone_flags)
170 {
171 	struct task_struct *kptr;
172 	struct __tasks_kfunc_map_value *v;
173 
174 	v = insert_lookup_task(task);
175 	if (!v)
176 		return 0;
177 
178 	kptr = bpf_kptr_xchg(&v->task, NULL);
179 	if (!kptr)
180 		return 0;
181 
182 	/* Kptr retrieved from map is never released. */
183 
184 	return 0;
185 }
186 
187 SEC("tp_btf/task_newtask")
188 __failure __msg("Unreleased reference")
189 int BPF_PROG(task_kfunc_get_unreleased, struct task_struct *task, u64 clone_flags)
190 {
191 	struct task_struct *kptr;
192 	struct __tasks_kfunc_map_value *v;
193 
194 	v = insert_lookup_task(task);
195 	if (!v)
196 		return 0;
197 
198 	kptr = bpf_task_kptr_get(&v->task);
199 	if (!kptr)
200 		return 0;
201 
202 	/* Kptr acquired above is never released. */
203 
204 	return 0;
205 }
206 
207 SEC("tp_btf/task_newtask")
208 __failure __msg("arg#0 is untrusted_ptr_or_null_ expected ptr_ or socket")
209 int BPF_PROG(task_kfunc_release_untrusted, struct task_struct *task, u64 clone_flags)
210 {
211 	struct __tasks_kfunc_map_value *v;
212 
213 	v = insert_lookup_task(task);
214 	if (!v)
215 		return 0;
216 
217 	/* Can't invoke bpf_task_release() on an untrusted pointer. */
218 	bpf_task_release(v->task);
219 
220 	return 0;
221 }
222 
223 SEC("tp_btf/task_newtask")
224 __failure __msg("arg#0 pointer type STRUCT task_struct must point")
225 int BPF_PROG(task_kfunc_release_fp, struct task_struct *task, u64 clone_flags)
226 {
227 	struct task_struct *acquired = (struct task_struct *)&clone_flags;
228 
229 	/* Cannot release random frame pointer. */
230 	bpf_task_release(acquired);
231 
232 	return 0;
233 }
234 
235 SEC("tp_btf/task_newtask")
236 __failure __msg("arg#0 is ptr_or_null_ expected ptr_ or socket")
237 int BPF_PROG(task_kfunc_release_null, struct task_struct *task, u64 clone_flags)
238 {
239 	struct __tasks_kfunc_map_value local, *v;
240 	long status;
241 	struct task_struct *acquired, *old;
242 	s32 pid;
243 
244 	status = bpf_probe_read_kernel(&pid, sizeof(pid), &task->pid);
245 	if (status)
246 		return 0;
247 
248 	local.task = NULL;
249 	status = bpf_map_update_elem(&__tasks_kfunc_map, &pid, &local, BPF_NOEXIST);
250 	if (status)
251 		return status;
252 
253 	v = bpf_map_lookup_elem(&__tasks_kfunc_map, &pid);
254 	if (!v)
255 		return -ENOENT;
256 
257 	acquired = bpf_task_acquire(task);
258 
259 	old = bpf_kptr_xchg(&v->task, acquired);
260 
261 	/* old cannot be passed to bpf_task_release() without a NULL check. */
262 	bpf_task_release(old);
263 	bpf_task_release(old);
264 
265 	return 0;
266 }
267 
268 SEC("tp_btf/task_newtask")
269 __failure __msg("release kernel function bpf_task_release expects")
270 int BPF_PROG(task_kfunc_release_unacquired, struct task_struct *task, u64 clone_flags)
271 {
272 	/* Cannot release trusted task pointer which was not acquired. */
273 	bpf_task_release(task);
274 
275 	return 0;
276 }
277 
278 SEC("tp_btf/task_newtask")
279 __failure __msg("arg#0 is ptr_or_null_ expected ptr_ or socket")
280 int BPF_PROG(task_kfunc_from_pid_no_null_check, struct task_struct *task, u64 clone_flags)
281 {
282 	struct task_struct *acquired;
283 
284 	acquired = bpf_task_from_pid(task->pid);
285 
286 	/* Releasing bpf_task_from_pid() lookup without a NULL check. */
287 	bpf_task_release(acquired);
288 
289 	return 0;
290 }
291 
292 SEC("lsm/task_free")
293 __failure __msg("reg type unsupported for arg#0 function")
294 int BPF_PROG(task_kfunc_from_lsm_task_free, struct task_struct *task)
295 {
296 	struct task_struct *acquired;
297 
298 	/* the argument of lsm task_free hook is untrusted. */
299 	acquired = bpf_task_acquire(task);
300 	bpf_task_release(acquired);
301 	return 0;
302 }
303