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
is_test_kfunc_task(void)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")
BPF_PROG(test_cgrp_acquire_release_argument,struct cgroup * cgrp,const char * path)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")
BPF_PROG(test_cgrp_acquire_leave_in_map,struct cgroup * cgrp,const char * path)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")
BPF_PROG(test_cgrp_xchg_release,struct cgroup * cgrp,const char * path)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")
BPF_PROG(test_cgrp_get_release,struct cgroup * cgrp,const char * path)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")
BPF_PROG(test_cgrp_get_ancestors,struct cgroup * cgrp,const char * path)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