1f583ddf1SDavid Vernet // SPDX-License-Identifier: GPL-2.0
2f583ddf1SDavid Vernet /* Copyright (c) 2022 Meta Platforms, Inc. and affiliates. */
3f583ddf1SDavid Vernet
4f583ddf1SDavid Vernet #include <vmlinux.h>
5f583ddf1SDavid Vernet #include <bpf/bpf_tracing.h>
6f583ddf1SDavid Vernet #include <bpf/bpf_helpers.h>
7f583ddf1SDavid Vernet
8f583ddf1SDavid Vernet #include "cgrp_kfunc_common.h"
9f583ddf1SDavid Vernet
10f583ddf1SDavid Vernet char _license[] SEC("license") = "GPL";
11f583ddf1SDavid Vernet
12f583ddf1SDavid Vernet int err, pid, invocations;
13f583ddf1SDavid Vernet
14f583ddf1SDavid Vernet /* Prototype for all of the program trace events below:
15f583ddf1SDavid Vernet *
16f583ddf1SDavid Vernet * TRACE_EVENT(cgroup_mkdir,
17f583ddf1SDavid Vernet * TP_PROTO(struct cgroup *cgrp, const char *path),
18f583ddf1SDavid Vernet * TP_ARGS(cgrp, path)
19f583ddf1SDavid Vernet */
20f583ddf1SDavid Vernet
is_test_kfunc_task(void)21f583ddf1SDavid Vernet static bool is_test_kfunc_task(void)
22f583ddf1SDavid Vernet {
23f583ddf1SDavid Vernet int cur_pid = bpf_get_current_pid_tgid() >> 32;
24f583ddf1SDavid Vernet bool same = pid == cur_pid;
25f583ddf1SDavid Vernet
26f583ddf1SDavid Vernet if (same)
27f583ddf1SDavid Vernet __sync_fetch_and_add(&invocations, 1);
28f583ddf1SDavid Vernet
29f583ddf1SDavid Vernet return same;
30f583ddf1SDavid Vernet }
31f583ddf1SDavid Vernet
32f583ddf1SDavid Vernet SEC("tp_btf/cgroup_mkdir")
BPF_PROG(test_cgrp_acquire_release_argument,struct cgroup * cgrp,const char * path)33f583ddf1SDavid Vernet int BPF_PROG(test_cgrp_acquire_release_argument, struct cgroup *cgrp, const char *path)
34f583ddf1SDavid Vernet {
35f583ddf1SDavid Vernet struct cgroup *acquired;
36f583ddf1SDavid Vernet
37f583ddf1SDavid Vernet if (!is_test_kfunc_task())
38f583ddf1SDavid Vernet return 0;
39f583ddf1SDavid Vernet
40f583ddf1SDavid Vernet acquired = bpf_cgroup_acquire(cgrp);
411d712839SDavid Vernet if (!acquired)
421d712839SDavid Vernet err = 1;
431d712839SDavid Vernet else
44f583ddf1SDavid Vernet bpf_cgroup_release(acquired);
45f583ddf1SDavid Vernet
46f583ddf1SDavid Vernet return 0;
47f583ddf1SDavid Vernet }
48f583ddf1SDavid Vernet
49f583ddf1SDavid Vernet SEC("tp_btf/cgroup_mkdir")
BPF_PROG(test_cgrp_acquire_leave_in_map,struct cgroup * cgrp,const char * path)50f583ddf1SDavid Vernet int BPF_PROG(test_cgrp_acquire_leave_in_map, struct cgroup *cgrp, const char *path)
51f583ddf1SDavid Vernet {
52f583ddf1SDavid Vernet long status;
53f583ddf1SDavid Vernet
54f583ddf1SDavid Vernet if (!is_test_kfunc_task())
55f583ddf1SDavid Vernet return 0;
56f583ddf1SDavid Vernet
57f583ddf1SDavid Vernet status = cgrps_kfunc_map_insert(cgrp);
58f583ddf1SDavid Vernet if (status)
59f583ddf1SDavid Vernet err = 1;
60f583ddf1SDavid Vernet
61f583ddf1SDavid Vernet return 0;
62f583ddf1SDavid Vernet }
63f583ddf1SDavid Vernet
64f583ddf1SDavid Vernet SEC("tp_btf/cgroup_mkdir")
BPF_PROG(test_cgrp_xchg_release,struct cgroup * cgrp,const char * path)65f583ddf1SDavid Vernet int BPF_PROG(test_cgrp_xchg_release, struct cgroup *cgrp, const char *path)
66f583ddf1SDavid Vernet {
670047d834SAlexei Starovoitov struct cgroup *kptr, *cg;
68f583ddf1SDavid Vernet struct __cgrps_kfunc_map_value *v;
69f583ddf1SDavid Vernet long status;
70f583ddf1SDavid Vernet
71f583ddf1SDavid Vernet if (!is_test_kfunc_task())
72f583ddf1SDavid Vernet return 0;
73f583ddf1SDavid Vernet
74f583ddf1SDavid Vernet status = cgrps_kfunc_map_insert(cgrp);
75f583ddf1SDavid Vernet if (status) {
76f583ddf1SDavid Vernet err = 1;
77f583ddf1SDavid Vernet return 0;
78f583ddf1SDavid Vernet }
79f583ddf1SDavid Vernet
80f583ddf1SDavid Vernet v = cgrps_kfunc_map_value_lookup(cgrp);
81f583ddf1SDavid Vernet if (!v) {
82f583ddf1SDavid Vernet err = 2;
83f583ddf1SDavid Vernet return 0;
84f583ddf1SDavid Vernet }
85f583ddf1SDavid Vernet
860047d834SAlexei Starovoitov kptr = v->cgrp;
870047d834SAlexei Starovoitov if (!kptr) {
880047d834SAlexei Starovoitov err = 4;
890047d834SAlexei Starovoitov return 0;
900047d834SAlexei Starovoitov }
910047d834SAlexei Starovoitov
920047d834SAlexei Starovoitov cg = bpf_cgroup_ancestor(kptr, 1);
930047d834SAlexei Starovoitov if (cg) /* verifier only check */
940047d834SAlexei Starovoitov bpf_cgroup_release(cg);
950047d834SAlexei Starovoitov
96f583ddf1SDavid Vernet kptr = bpf_kptr_xchg(&v->cgrp, NULL);
97f583ddf1SDavid Vernet if (!kptr) {
98f583ddf1SDavid Vernet err = 3;
99f583ddf1SDavid Vernet return 0;
100f583ddf1SDavid Vernet }
101f583ddf1SDavid Vernet
102f583ddf1SDavid Vernet bpf_cgroup_release(kptr);
103f583ddf1SDavid Vernet
104f583ddf1SDavid Vernet return 0;
105f583ddf1SDavid Vernet }
106f583ddf1SDavid Vernet
107f583ddf1SDavid Vernet SEC("tp_btf/cgroup_mkdir")
BPF_PROG(test_cgrp_get_release,struct cgroup * cgrp,const char * path)108f583ddf1SDavid Vernet int BPF_PROG(test_cgrp_get_release, struct cgroup *cgrp, const char *path)
109f583ddf1SDavid Vernet {
110f583ddf1SDavid Vernet struct cgroup *kptr;
111f583ddf1SDavid Vernet struct __cgrps_kfunc_map_value *v;
112f583ddf1SDavid Vernet long status;
113f583ddf1SDavid Vernet
114f583ddf1SDavid Vernet if (!is_test_kfunc_task())
115f583ddf1SDavid Vernet return 0;
116f583ddf1SDavid Vernet
117f583ddf1SDavid Vernet status = cgrps_kfunc_map_insert(cgrp);
118f583ddf1SDavid Vernet if (status) {
119f583ddf1SDavid Vernet err = 1;
120f583ddf1SDavid Vernet return 0;
121f583ddf1SDavid Vernet }
122f583ddf1SDavid Vernet
123f583ddf1SDavid Vernet v = cgrps_kfunc_map_value_lookup(cgrp);
124f583ddf1SDavid Vernet if (!v) {
125f583ddf1SDavid Vernet err = 2;
126f583ddf1SDavid Vernet return 0;
127f583ddf1SDavid Vernet }
128f583ddf1SDavid Vernet
129*6499fe6eSDavid Vernet bpf_rcu_read_lock();
130*6499fe6eSDavid Vernet kptr = v->cgrp;
131*6499fe6eSDavid Vernet if (!kptr)
132f583ddf1SDavid Vernet err = 3;
133*6499fe6eSDavid Vernet bpf_rcu_read_unlock();
134f583ddf1SDavid Vernet
135f583ddf1SDavid Vernet return 0;
136f583ddf1SDavid Vernet }
137227a89cfSDavid Vernet
138227a89cfSDavid Vernet SEC("tp_btf/cgroup_mkdir")
BPF_PROG(test_cgrp_get_ancestors,struct cgroup * cgrp,const char * path)139227a89cfSDavid Vernet int BPF_PROG(test_cgrp_get_ancestors, struct cgroup *cgrp, const char *path)
140227a89cfSDavid Vernet {
141227a89cfSDavid Vernet struct cgroup *self, *ancestor1, *invalid;
142227a89cfSDavid Vernet
143227a89cfSDavid Vernet if (!is_test_kfunc_task())
144227a89cfSDavid Vernet return 0;
145227a89cfSDavid Vernet
146227a89cfSDavid Vernet self = bpf_cgroup_ancestor(cgrp, cgrp->level);
147227a89cfSDavid Vernet if (!self) {
148227a89cfSDavid Vernet err = 1;
149227a89cfSDavid Vernet return 0;
150227a89cfSDavid Vernet }
151227a89cfSDavid Vernet
152227a89cfSDavid Vernet if (self->self.id != cgrp->self.id) {
153227a89cfSDavid Vernet bpf_cgroup_release(self);
154227a89cfSDavid Vernet err = 2;
155227a89cfSDavid Vernet return 0;
156227a89cfSDavid Vernet }
157227a89cfSDavid Vernet bpf_cgroup_release(self);
158227a89cfSDavid Vernet
159227a89cfSDavid Vernet ancestor1 = bpf_cgroup_ancestor(cgrp, cgrp->level - 1);
160227a89cfSDavid Vernet if (!ancestor1) {
161227a89cfSDavid Vernet err = 3;
162227a89cfSDavid Vernet return 0;
163227a89cfSDavid Vernet }
164227a89cfSDavid Vernet bpf_cgroup_release(ancestor1);
165227a89cfSDavid Vernet
166227a89cfSDavid Vernet invalid = bpf_cgroup_ancestor(cgrp, 10000);
167227a89cfSDavid Vernet if (invalid) {
168227a89cfSDavid Vernet bpf_cgroup_release(invalid);
169227a89cfSDavid Vernet err = 4;
170227a89cfSDavid Vernet return 0;
171227a89cfSDavid Vernet }
172227a89cfSDavid Vernet
173227a89cfSDavid Vernet invalid = bpf_cgroup_ancestor(cgrp, -1);
174227a89cfSDavid Vernet if (invalid) {
175227a89cfSDavid Vernet bpf_cgroup_release(invalid);
176227a89cfSDavid Vernet err = 5;
177227a89cfSDavid Vernet return 0;
178227a89cfSDavid Vernet }
179227a89cfSDavid Vernet
180227a89cfSDavid Vernet return 0;
181227a89cfSDavid Vernet }
182d0093aaeSTejun Heo
183d0093aaeSTejun Heo SEC("tp_btf/cgroup_mkdir")
BPF_PROG(test_cgrp_from_id,struct cgroup * cgrp,const char * path)184d0093aaeSTejun Heo int BPF_PROG(test_cgrp_from_id, struct cgroup *cgrp, const char *path)
185d0093aaeSTejun Heo {
186d0093aaeSTejun Heo struct cgroup *parent, *res;
187d0093aaeSTejun Heo u64 parent_cgid;
188d0093aaeSTejun Heo
189d0093aaeSTejun Heo if (!is_test_kfunc_task())
190d0093aaeSTejun Heo return 0;
191d0093aaeSTejun Heo
192d0093aaeSTejun Heo /* @cgrp's ID is not visible yet, let's test with the parent */
193d0093aaeSTejun Heo parent = bpf_cgroup_ancestor(cgrp, cgrp->level - 1);
194d0093aaeSTejun Heo if (!parent) {
195d0093aaeSTejun Heo err = 1;
196d0093aaeSTejun Heo return 0;
197d0093aaeSTejun Heo }
198d0093aaeSTejun Heo
199d0093aaeSTejun Heo parent_cgid = parent->kn->id;
200d0093aaeSTejun Heo bpf_cgroup_release(parent);
201d0093aaeSTejun Heo
202d0093aaeSTejun Heo res = bpf_cgroup_from_id(parent_cgid);
203d0093aaeSTejun Heo if (!res) {
204d0093aaeSTejun Heo err = 2;
205d0093aaeSTejun Heo return 0;
206d0093aaeSTejun Heo }
207d0093aaeSTejun Heo
208d0093aaeSTejun Heo bpf_cgroup_release(res);
209d0093aaeSTejun Heo
210d0093aaeSTejun Heo if (res != parent) {
211d0093aaeSTejun Heo err = 3;
212d0093aaeSTejun Heo return 0;
213d0093aaeSTejun Heo }
214d0093aaeSTejun Heo
215d0093aaeSTejun Heo res = bpf_cgroup_from_id((u64)-1);
216d0093aaeSTejun Heo if (res) {
217d0093aaeSTejun Heo bpf_cgroup_release(res);
218d0093aaeSTejun Heo err = 4;
219d0093aaeSTejun Heo return 0;
220d0093aaeSTejun Heo }
221d0093aaeSTejun Heo
222d0093aaeSTejun Heo return 0;
223d0093aaeSTejun Heo }
224