xref: /linux/tools/testing/selftests/bpf/progs/task_kfunc_common.h (revision 9b8107553424fd87955fed257a807672c2097297)
1 /* SPDX-License-Identifier: GPL-2.0 */
2 /* Copyright (c) 2022 Meta Platforms, Inc. and affiliates. */
3 
4 #ifndef _TASK_KFUNC_COMMON_H
5 #define _TASK_KFUNC_COMMON_H
6 
7 #include <errno.h>
8 #include <vmlinux.h>
9 #include <bpf/bpf_helpers.h>
10 #include <bpf/bpf_tracing.h>
11 
12 struct __tasks_kfunc_map_value {
13 	struct task_struct __kptr_ref * task;
14 };
15 
16 struct hash_map {
17 	__uint(type, BPF_MAP_TYPE_HASH);
18 	__type(key, int);
19 	__type(value, struct __tasks_kfunc_map_value);
20 	__uint(max_entries, 1);
21 } __tasks_kfunc_map SEC(".maps");
22 
23 struct task_struct *bpf_task_acquire(struct task_struct *p) __ksym;
24 struct task_struct *bpf_task_kptr_get(struct task_struct **pp) __ksym;
25 void bpf_task_release(struct task_struct *p) __ksym;
26 
27 static inline struct __tasks_kfunc_map_value *tasks_kfunc_map_value_lookup(struct task_struct *p)
28 {
29 	s32 pid;
30 	long status;
31 
32 	status = bpf_probe_read_kernel(&pid, sizeof(pid), &p->pid);
33 	if (status)
34 		return NULL;
35 
36 	return bpf_map_lookup_elem(&__tasks_kfunc_map, &pid);
37 }
38 
39 static inline int tasks_kfunc_map_insert(struct task_struct *p)
40 {
41 	struct __tasks_kfunc_map_value local, *v;
42 	long status;
43 	struct task_struct *acquired, *old;
44 	s32 pid;
45 
46 	status = bpf_probe_read_kernel(&pid, sizeof(pid), &p->pid);
47 	if (status)
48 		return status;
49 
50 	local.task = NULL;
51 	status = bpf_map_update_elem(&__tasks_kfunc_map, &pid, &local, BPF_NOEXIST);
52 	if (status)
53 		return status;
54 
55 	v = bpf_map_lookup_elem(&__tasks_kfunc_map, &pid);
56 	if (!v) {
57 		bpf_map_delete_elem(&__tasks_kfunc_map, &pid);
58 		return -ENOENT;
59 	}
60 
61 	acquired = bpf_task_acquire(p);
62 	old = bpf_kptr_xchg(&v->task, acquired);
63 	if (old) {
64 		bpf_task_release(old);
65 		return -EEXIST;
66 	}
67 
68 	return 0;
69 }
70 
71 #endif /* _TASK_KFUNC_COMMON_H */
72