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 int err, pid, invocations;
13 
14 /* Prototype for all of the program trace events below:
15  *
16  * TRACE_EVENT(cgroup_mkdir,
17  *         TP_PROTO(struct cgroup *cgrp, const char *path),
18  *         TP_ARGS(cgrp, path)
19  */
20 
21 static bool is_test_kfunc_task(void)
22 {
23 	int cur_pid = bpf_get_current_pid_tgid() >> 32;
24 	bool same = pid == cur_pid;
25 
26 	if (same)
27 		__sync_fetch_and_add(&invocations, 1);
28 
29 	return same;
30 }
31 
32 SEC("tp_btf/cgroup_mkdir")
33 int BPF_PROG(test_cgrp_acquire_release_argument, struct cgroup *cgrp, const char *path)
34 {
35 	struct cgroup *acquired;
36 
37 	if (!is_test_kfunc_task())
38 		return 0;
39 
40 	acquired = bpf_cgroup_acquire(cgrp);
41 	bpf_cgroup_release(acquired);
42 
43 	return 0;
44 }
45 
46 SEC("tp_btf/cgroup_mkdir")
47 int BPF_PROG(test_cgrp_acquire_leave_in_map, struct cgroup *cgrp, const char *path)
48 {
49 	long status;
50 
51 	if (!is_test_kfunc_task())
52 		return 0;
53 
54 	status = cgrps_kfunc_map_insert(cgrp);
55 	if (status)
56 		err = 1;
57 
58 	return 0;
59 }
60 
61 SEC("tp_btf/cgroup_mkdir")
62 int BPF_PROG(test_cgrp_xchg_release, struct cgroup *cgrp, const char *path)
63 {
64 	struct cgroup *kptr;
65 	struct __cgrps_kfunc_map_value *v;
66 	long status;
67 
68 	if (!is_test_kfunc_task())
69 		return 0;
70 
71 	status = cgrps_kfunc_map_insert(cgrp);
72 	if (status) {
73 		err = 1;
74 		return 0;
75 	}
76 
77 	v = cgrps_kfunc_map_value_lookup(cgrp);
78 	if (!v) {
79 		err = 2;
80 		return 0;
81 	}
82 
83 	kptr = bpf_kptr_xchg(&v->cgrp, NULL);
84 	if (!kptr) {
85 		err = 3;
86 		return 0;
87 	}
88 
89 	bpf_cgroup_release(kptr);
90 
91 	return 0;
92 }
93 
94 SEC("tp_btf/cgroup_mkdir")
95 int BPF_PROG(test_cgrp_get_release, struct cgroup *cgrp, const char *path)
96 {
97 	struct cgroup *kptr;
98 	struct __cgrps_kfunc_map_value *v;
99 	long status;
100 
101 	if (!is_test_kfunc_task())
102 		return 0;
103 
104 	status = cgrps_kfunc_map_insert(cgrp);
105 	if (status) {
106 		err = 1;
107 		return 0;
108 	}
109 
110 	v = cgrps_kfunc_map_value_lookup(cgrp);
111 	if (!v) {
112 		err = 2;
113 		return 0;
114 	}
115 
116 	kptr = bpf_cgroup_kptr_get(&v->cgrp);
117 	if (!kptr) {
118 		err = 3;
119 		return 0;
120 	}
121 
122 	bpf_cgroup_release(kptr);
123 
124 	return 0;
125 }
126 
127 SEC("tp_btf/cgroup_mkdir")
128 int BPF_PROG(test_cgrp_get_ancestors, struct cgroup *cgrp, const char *path)
129 {
130 	struct cgroup *self, *ancestor1, *invalid;
131 
132 	if (!is_test_kfunc_task())
133 		return 0;
134 
135 	self = bpf_cgroup_ancestor(cgrp, cgrp->level);
136 	if (!self) {
137 		err = 1;
138 		return 0;
139 	}
140 
141 	if (self->self.id != cgrp->self.id) {
142 		bpf_cgroup_release(self);
143 		err = 2;
144 		return 0;
145 	}
146 	bpf_cgroup_release(self);
147 
148 	ancestor1 = bpf_cgroup_ancestor(cgrp, cgrp->level - 1);
149 	if (!ancestor1) {
150 		err = 3;
151 		return 0;
152 	}
153 	bpf_cgroup_release(ancestor1);
154 
155 	invalid = bpf_cgroup_ancestor(cgrp, 10000);
156 	if (invalid) {
157 		bpf_cgroup_release(invalid);
158 		err = 4;
159 		return 0;
160 	}
161 
162 	invalid = bpf_cgroup_ancestor(cgrp, -1);
163 	if (invalid) {
164 		bpf_cgroup_release(invalid);
165 		err = 5;
166 		return 0;
167 	}
168 
169 	return 0;
170 }
171