xref: /linux/tools/testing/selftests/bpf/progs/task_kfunc_failure.c (revision 5a8cd539ac19f7a68e68e1d25ef9ca2ff55b8500)
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