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_experimental.h"
9 #include "bpf_misc.h"
10 #include "task_kfunc_common.h"
11
12 char _license[] SEC("license") = "GPL";
13
14 /* Prototype for all of the program trace events below:
15 *
16 * TRACE_EVENT(task_newtask,
17 * TP_PROTO(struct task_struct *p, u64 clone_flags)
18 */
19
insert_lookup_task(struct task_struct * task)20 static struct __tasks_kfunc_map_value *insert_lookup_task(struct task_struct *task)
21 {
22 int status;
23
24 status = tasks_kfunc_map_insert(task);
25 if (status)
26 return NULL;
27
28 return tasks_kfunc_map_value_lookup(task);
29 }
30
31 SEC("tp_btf/task_newtask")
32 __failure __msg("Possibly NULL pointer passed to trusted R1")
BPF_PROG(task_kfunc_acquire_untrusted,struct task_struct * task,u64 clone_flags)33 int BPF_PROG(task_kfunc_acquire_untrusted, struct task_struct *task, u64 clone_flags)
34 {
35 struct task_struct *acquired;
36 struct __tasks_kfunc_map_value *v;
37
38 v = insert_lookup_task(task);
39 if (!v)
40 return 0;
41
42 /* Can't invoke bpf_task_acquire() on an untrusted pointer. */
43 acquired = bpf_task_acquire(v->task);
44 if (!acquired)
45 return 0;
46
47 bpf_task_release(acquired);
48
49 return 0;
50 }
51
52 SEC("tp_btf/task_newtask")
53 __failure __msg("R1 is fp expected STRUCT task_struct")
BPF_PROG(task_kfunc_acquire_fp,struct task_struct * task,u64 clone_flags)54 int BPF_PROG(task_kfunc_acquire_fp, struct task_struct *task, u64 clone_flags)
55 {
56 struct task_struct *acquired, *stack_task = (struct task_struct *)&clone_flags;
57
58 /* Can't invoke bpf_task_acquire() on a random frame pointer. */
59 acquired = bpf_task_acquire((struct task_struct *)&stack_task);
60 if (!acquired)
61 return 0;
62
63 bpf_task_release(acquired);
64
65 return 0;
66 }
67
68 SEC("kretprobe/free_task")
69 __failure __msg("calling kernel function bpf_task_acquire is not allowed")
BPF_PROG(task_kfunc_acquire_unsafe_kretprobe,struct task_struct * task,u64 clone_flags)70 int BPF_PROG(task_kfunc_acquire_unsafe_kretprobe, struct task_struct *task, u64 clone_flags)
71 {
72 struct task_struct *acquired;
73
74 /* Can't call bpf_task_acquire() or bpf_task_release() in an untrusted prog. */
75 acquired = bpf_task_acquire(task);
76 if (!acquired)
77 return 0;
78 bpf_task_release(acquired);
79
80 return 0;
81 }
82
83 SEC("kretprobe/free_task")
84 __failure __msg("calling kernel function bpf_task_acquire is not allowed")
BPF_PROG(task_kfunc_acquire_unsafe_kretprobe_rcu,struct task_struct * task,u64 clone_flags)85 int BPF_PROG(task_kfunc_acquire_unsafe_kretprobe_rcu, struct task_struct *task, u64 clone_flags)
86 {
87 struct task_struct *acquired;
88
89 bpf_rcu_read_lock();
90 if (!task) {
91 bpf_rcu_read_unlock();
92 return 0;
93 }
94 /* Can't call bpf_task_acquire() or bpf_task_release() in an untrusted prog. */
95 acquired = bpf_task_acquire(task);
96 if (acquired)
97 bpf_task_release(acquired);
98 bpf_rcu_read_unlock();
99
100 return 0;
101 }
102
103 SEC("tp_btf/task_newtask")
104 __failure __msg("Possibly NULL pointer passed to trusted R1")
BPF_PROG(task_kfunc_acquire_null,struct task_struct * task,u64 clone_flags)105 int BPF_PROG(task_kfunc_acquire_null, struct task_struct *task, u64 clone_flags)
106 {
107 struct task_struct *acquired;
108
109 /* Can't invoke bpf_task_acquire() on a NULL pointer. */
110 acquired = bpf_task_acquire(NULL);
111 if (!acquired)
112 return 0;
113 bpf_task_release(acquired);
114
115 return 0;
116 }
117
118 SEC("tp_btf/task_newtask")
119 __failure __msg("Unreleased reference")
BPF_PROG(task_kfunc_acquire_unreleased,struct task_struct * task,u64 clone_flags)120 int BPF_PROG(task_kfunc_acquire_unreleased, struct task_struct *task, u64 clone_flags)
121 {
122 struct task_struct *acquired;
123
124 acquired = bpf_task_acquire(task);
125
126 /* Acquired task is never released. */
127 __sink(acquired);
128
129 return 0;
130 }
131
132 SEC("tp_btf/task_newtask")
133 __failure __msg("Unreleased reference")
BPF_PROG(task_kfunc_xchg_unreleased,struct task_struct * task,u64 clone_flags)134 int BPF_PROG(task_kfunc_xchg_unreleased, struct task_struct *task, u64 clone_flags)
135 {
136 struct task_struct *kptr;
137 struct __tasks_kfunc_map_value *v;
138
139 v = insert_lookup_task(task);
140 if (!v)
141 return 0;
142
143 kptr = bpf_kptr_xchg(&v->task, NULL);
144 if (!kptr)
145 return 0;
146
147 /* Kptr retrieved from map is never released. */
148
149 return 0;
150 }
151
152 SEC("tp_btf/task_newtask")
153 __failure __msg("Possibly NULL pointer passed to trusted R1")
BPF_PROG(task_kfunc_acquire_release_no_null_check,struct task_struct * task,u64 clone_flags)154 int BPF_PROG(task_kfunc_acquire_release_no_null_check, struct task_struct *task, u64 clone_flags)
155 {
156 struct task_struct *acquired;
157
158 acquired = bpf_task_acquire(task);
159 /* Can't invoke bpf_task_release() on an acquired task without a NULL check. */
160 bpf_task_release(acquired);
161
162 return 0;
163 }
164
165 SEC("tp_btf/task_newtask")
166 __failure __msg("Possibly NULL pointer passed to trusted R1")
BPF_PROG(task_kfunc_release_untrusted,struct task_struct * task,u64 clone_flags)167 int BPF_PROG(task_kfunc_release_untrusted, struct task_struct *task, u64 clone_flags)
168 {
169 struct __tasks_kfunc_map_value *v;
170
171 v = insert_lookup_task(task);
172 if (!v)
173 return 0;
174
175 /* Can't invoke bpf_task_release() on an untrusted pointer. */
176 bpf_task_release(v->task);
177
178 return 0;
179 }
180
181 SEC("tp_btf/task_newtask")
182 __failure __msg("release kfunc bpf_task_release expects referenced PTR_TO_BTF_ID passed to R1")
BPF_PROG(task_kfunc_release_fp,struct task_struct * task,u64 clone_flags)183 int BPF_PROG(task_kfunc_release_fp, struct task_struct *task, u64 clone_flags)
184 {
185 struct task_struct *acquired = (struct task_struct *)&clone_flags;
186
187 /* Cannot release random frame pointer. */
188 bpf_task_release(acquired);
189
190 return 0;
191 }
192
193 SEC("tp_btf/task_newtask")
194 __failure __msg("Possibly NULL pointer passed to trusted R1")
BPF_PROG(task_kfunc_release_null,struct task_struct * task,u64 clone_flags)195 int BPF_PROG(task_kfunc_release_null, struct task_struct *task, u64 clone_flags)
196 {
197 struct __tasks_kfunc_map_value local, *v;
198 long status;
199 struct task_struct *acquired, *old;
200 s32 pid;
201
202 status = bpf_probe_read_kernel(&pid, sizeof(pid), &task->pid);
203 if (status)
204 return 0;
205
206 local.task = NULL;
207 status = bpf_map_update_elem(&__tasks_kfunc_map, &pid, &local, BPF_NOEXIST);
208 if (status)
209 return status;
210
211 v = bpf_map_lookup_elem(&__tasks_kfunc_map, &pid);
212 if (!v)
213 return -ENOENT;
214
215 acquired = bpf_task_acquire(task);
216 if (!acquired)
217 return -EEXIST;
218
219 old = bpf_kptr_xchg(&v->task, acquired);
220
221 /* old cannot be passed to bpf_task_release() without a NULL check. */
222 bpf_task_release(old);
223
224 return 0;
225 }
226
227 SEC("tp_btf/task_newtask")
228 __failure __msg("release kfunc bpf_task_release expects referenced PTR_TO_BTF_ID passed to R1")
BPF_PROG(task_kfunc_release_unacquired,struct task_struct * task,u64 clone_flags)229 int BPF_PROG(task_kfunc_release_unacquired, struct task_struct *task, u64 clone_flags)
230 {
231 /* Cannot release trusted task pointer which was not acquired. */
232 bpf_task_release(task);
233
234 return 0;
235 }
236
237 SEC("tp_btf/task_newtask")
238 __failure __msg("bpf_obj_drop cannot be used in tracing programs on types with NMI unsafe fields")
BPF_PROG(task_kfunc_obj_drop_with_kptr,struct task_struct * task,u64 clone_flags)239 int BPF_PROG(task_kfunc_obj_drop_with_kptr, struct task_struct *task, u64 clone_flags)
240 {
241 struct __tasks_kfunc_map_value *local;
242
243 local = bpf_obj_new(typeof(*local));
244 if (!local)
245 return 0;
246
247 bpf_obj_drop(local);
248 return 0;
249 }
250
251 SEC("tp_btf/task_newtask")
252 __failure __msg("bpf_obj_drop cannot be used in tracing programs on types with NMI unsafe fields")
BPF_PROG(task_kfunc_obj_drop_nmi_with_kptr,struct task_struct * task,u64 clone_flags)253 int BPF_PROG(task_kfunc_obj_drop_nmi_with_kptr, struct task_struct *task,
254 u64 clone_flags)
255 {
256 struct __tasks_kfunc_map_value *local;
257 struct task_struct *acquired, *old;
258
259 (void)clone_flags;
260
261 local = bpf_obj_new(typeof(*local));
262 if (!local)
263 return 0;
264
265 acquired = bpf_task_acquire(task);
266 if (acquired) {
267 old = bpf_kptr_xchg(&local->task, acquired);
268 if (old)
269 bpf_task_release(old);
270 }
271
272 bpf_obj_drop(local);
273 return 0;
274 }
275
276 SEC("tp_btf/task_newtask")
277 __failure __msg("Possibly NULL pointer passed to trusted R1")
BPF_PROG(task_kfunc_from_pid_no_null_check,struct task_struct * task,u64 clone_flags)278 int BPF_PROG(task_kfunc_from_pid_no_null_check, struct task_struct *task, u64 clone_flags)
279 {
280 struct task_struct *acquired;
281
282 acquired = bpf_task_from_pid(task->pid);
283
284 /* Releasing bpf_task_from_pid() lookup without a NULL check. */
285 bpf_task_release(acquired);
286
287 return 0;
288 }
289
290 SEC("tp_btf/task_newtask")
291 __failure __msg("Possibly NULL pointer passed to trusted R1")
BPF_PROG(task_kfunc_from_vpid_no_null_check,struct task_struct * task,u64 clone_flags)292 int BPF_PROG(task_kfunc_from_vpid_no_null_check, struct task_struct *task, u64 clone_flags)
293 {
294 struct task_struct *acquired;
295
296 acquired = bpf_task_from_vpid(task->pid);
297
298 /* Releasing bpf_task_from_vpid() lookup without a NULL check. */
299 bpf_task_release(acquired);
300
301 return 0;
302 }
303
304 SEC("lsm/task_free")
305 __failure __msg("R1 must be a rcu pointer")
BPF_PROG(task_kfunc_from_lsm_task_free,struct task_struct * task)306 int BPF_PROG(task_kfunc_from_lsm_task_free, struct task_struct *task)
307 {
308 struct task_struct *acquired;
309
310 /* the argument of lsm task_free hook is untrusted. */
311 acquired = bpf_task_acquire(task);
312 if (!acquired)
313 return 0;
314
315 bpf_task_release(acquired);
316 return 0;
317 }
318
319 SEC("tp_btf/task_newtask")
320 __failure __msg("access beyond the end of member comm")
BPF_PROG(task_access_comm1,struct task_struct * task,u64 clone_flags)321 int BPF_PROG(task_access_comm1, struct task_struct *task, u64 clone_flags)
322 {
323 bpf_strncmp(task->comm, 17, "foo");
324 return 0;
325 }
326
327 SEC("tp_btf/task_newtask")
328 __failure __msg("access beyond the end of member comm")
BPF_PROG(task_access_comm2,struct task_struct * task,u64 clone_flags)329 int BPF_PROG(task_access_comm2, struct task_struct *task, u64 clone_flags)
330 {
331 bpf_strncmp(task->comm + 1, 16, "foo");
332 return 0;
333 }
334
335 SEC("tp_btf/task_newtask")
336 __failure __msg("write into memory")
BPF_PROG(task_access_comm3,struct task_struct * task,u64 clone_flags)337 int BPF_PROG(task_access_comm3, struct task_struct *task, u64 clone_flags)
338 {
339 bpf_probe_read_kernel(task->comm, 16, task->comm);
340 return 0;
341 }
342
343 SEC("fentry/__set_task_comm")
344 __failure __msg("R1 type=ptr_ expected")
BPF_PROG(task_access_comm4,struct task_struct * task,const char * buf,bool exec)345 int BPF_PROG(task_access_comm4, struct task_struct *task, const char *buf, bool exec)
346 {
347 /*
348 * task->comm is a legacy ptr_to_btf_id. The verifier cannot guarantee
349 * its safety. Hence it cannot be accessed with normal load insns.
350 */
351 bpf_strncmp(task->comm, 16, "foo");
352 return 0;
353 }
354
355 SEC("tp_btf/task_newtask")
356 __failure __msg("release kfunc bpf_task_release expects referenced PTR_TO_BTF_ID passed to R1")
BPF_PROG(task_kfunc_release_in_map,struct task_struct * task,u64 clone_flags)357 int BPF_PROG(task_kfunc_release_in_map, struct task_struct *task, u64 clone_flags)
358 {
359 struct task_struct *local;
360 struct __tasks_kfunc_map_value *v;
361
362 if (tasks_kfunc_map_insert(task))
363 return 0;
364
365 v = tasks_kfunc_map_value_lookup(task);
366 if (!v)
367 return 0;
368
369 bpf_rcu_read_lock();
370 local = v->task;
371 if (!local) {
372 bpf_rcu_read_unlock();
373 return 0;
374 }
375 /* Can't release a kptr that's still stored in a map. */
376 bpf_task_release(local);
377 bpf_rcu_read_unlock();
378
379 return 0;
380 }
381
382 SEC("?fentry.s/" SYS_PREFIX "sys_getpgid")
383 __failure __msg("R1 must be a rcu pointer")
BPF_PROG(task_kfunc_acquire_after_final_spin_unlock)384 int BPF_PROG(task_kfunc_acquire_after_final_spin_unlock)
385 {
386 struct task_kptr_lock_value *v;
387 struct task_struct *task, *acquired;
388 int key = 0;
389
390 v = bpf_map_lookup_elem(&task_kptr_lock_map, &key);
391 if (!v)
392 return 0;
393
394 bpf_spin_lock(&v->lock);
395 task = v->task;
396 bpf_spin_unlock(&v->lock);
397 if (!task)
398 return 0;
399
400 acquired = bpf_task_acquire(task);
401 if (acquired)
402 bpf_task_release(acquired);
403 return 0;
404 }
405
406 SEC("?fentry.s/" SYS_PREFIX "sys_getpgid")
407 __failure __msg("R1 must be a rcu pointer")
BPF_PROG(task_kfunc_acquire_after_preempt_enable)408 int BPF_PROG(task_kfunc_acquire_after_preempt_enable)
409 {
410 struct task_kptr_lock_value *v;
411 struct task_struct *task, *acquired;
412 int key = 0;
413
414 v = bpf_map_lookup_elem(&task_kptr_lock_map, &key);
415 if (!v)
416 return 0;
417
418 bpf_preempt_disable();
419 task = v->task;
420 bpf_preempt_enable();
421 if (!task)
422 return 0;
423
424 acquired = bpf_task_acquire(task);
425 if (acquired)
426 bpf_task_release(acquired);
427 return 0;
428 }
429
430 SEC("?fentry.s/" SYS_PREFIX "sys_getpgid")
431 __failure __msg("R1 must be a rcu pointer")
BPF_PROG(task_kfunc_acquire_after_irq_restore)432 int BPF_PROG(task_kfunc_acquire_after_irq_restore)
433 {
434 struct task_kptr_lock_value *v;
435 struct task_struct *task, *acquired;
436 unsigned long flags;
437 int key = 0;
438
439 v = bpf_map_lookup_elem(&task_kptr_lock_map, &key);
440 if (!v)
441 return 0;
442
443 bpf_local_irq_save(&flags);
444 task = v->task;
445 bpf_local_irq_restore(&flags);
446 if (!task)
447 return 0;
448
449 acquired = bpf_task_acquire(task);
450 if (acquired)
451 bpf_task_release(acquired);
452 return 0;
453 }
454