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 if (!acquired) 42 err = 1; 43 else 44 bpf_cgroup_release(acquired); 45 46 return 0; 47 } 48 49 SEC("tp_btf/cgroup_mkdir") 50 int BPF_PROG(test_cgrp_acquire_leave_in_map, struct cgroup *cgrp, const char *path) 51 { 52 long status; 53 54 if (!is_test_kfunc_task()) 55 return 0; 56 57 status = cgrps_kfunc_map_insert(cgrp); 58 if (status) 59 err = 1; 60 61 return 0; 62 } 63 64 SEC("tp_btf/cgroup_mkdir") 65 int BPF_PROG(test_cgrp_xchg_release, struct cgroup *cgrp, const char *path) 66 { 67 struct cgroup *kptr, *cg; 68 struct __cgrps_kfunc_map_value *v; 69 long status; 70 71 if (!is_test_kfunc_task()) 72 return 0; 73 74 status = cgrps_kfunc_map_insert(cgrp); 75 if (status) { 76 err = 1; 77 return 0; 78 } 79 80 v = cgrps_kfunc_map_value_lookup(cgrp); 81 if (!v) { 82 err = 2; 83 return 0; 84 } 85 86 kptr = v->cgrp; 87 if (!kptr) { 88 err = 4; 89 return 0; 90 } 91 92 cg = bpf_cgroup_ancestor(kptr, 1); 93 if (cg) /* verifier only check */ 94 bpf_cgroup_release(cg); 95 96 kptr = bpf_kptr_xchg(&v->cgrp, NULL); 97 if (!kptr) { 98 err = 3; 99 return 0; 100 } 101 102 bpf_cgroup_release(kptr); 103 104 return 0; 105 } 106 107 SEC("tp_btf/cgroup_mkdir") 108 int BPF_PROG(test_cgrp_get_release, struct cgroup *cgrp, const char *path) 109 { 110 struct cgroup *kptr; 111 struct __cgrps_kfunc_map_value *v; 112 long status; 113 114 if (!is_test_kfunc_task()) 115 return 0; 116 117 status = cgrps_kfunc_map_insert(cgrp); 118 if (status) { 119 err = 1; 120 return 0; 121 } 122 123 v = cgrps_kfunc_map_value_lookup(cgrp); 124 if (!v) { 125 err = 2; 126 return 0; 127 } 128 129 bpf_rcu_read_lock(); 130 kptr = v->cgrp; 131 if (!kptr) 132 err = 3; 133 bpf_rcu_read_unlock(); 134 135 return 0; 136 } 137 138 SEC("tp_btf/cgroup_mkdir") 139 int BPF_PROG(test_cgrp_get_ancestors, struct cgroup *cgrp, const char *path) 140 { 141 struct cgroup *self, *ancestor1, *invalid; 142 143 if (!is_test_kfunc_task()) 144 return 0; 145 146 self = bpf_cgroup_ancestor(cgrp, cgrp->level); 147 if (!self) { 148 err = 1; 149 return 0; 150 } 151 152 if (self->self.id != cgrp->self.id) { 153 bpf_cgroup_release(self); 154 err = 2; 155 return 0; 156 } 157 bpf_cgroup_release(self); 158 159 ancestor1 = bpf_cgroup_ancestor(cgrp, cgrp->level - 1); 160 if (!ancestor1) { 161 err = 3; 162 return 0; 163 } 164 bpf_cgroup_release(ancestor1); 165 166 invalid = bpf_cgroup_ancestor(cgrp, 10000); 167 if (invalid) { 168 bpf_cgroup_release(invalid); 169 err = 4; 170 return 0; 171 } 172 173 invalid = bpf_cgroup_ancestor(cgrp, -1); 174 if (invalid) { 175 bpf_cgroup_release(invalid); 176 err = 5; 177 return 0; 178 } 179 180 return 0; 181 } 182 183 SEC("tp_btf/cgroup_mkdir") 184 int BPF_PROG(test_cgrp_from_id, struct cgroup *cgrp, const char *path) 185 { 186 struct cgroup *parent, *res; 187 u64 parent_cgid; 188 189 if (!is_test_kfunc_task()) 190 return 0; 191 192 /* @cgrp's ID is not visible yet, let's test with the parent */ 193 parent = bpf_cgroup_ancestor(cgrp, cgrp->level - 1); 194 if (!parent) { 195 err = 1; 196 return 0; 197 } 198 199 parent_cgid = parent->kn->id; 200 bpf_cgroup_release(parent); 201 202 res = bpf_cgroup_from_id(parent_cgid); 203 if (!res) { 204 err = 2; 205 return 0; 206 } 207 208 bpf_cgroup_release(res); 209 210 if (res != parent) { 211 err = 3; 212 return 0; 213 } 214 215 res = bpf_cgroup_from_id((u64)-1); 216 if (res) { 217 bpf_cgroup_release(res); 218 err = 4; 219 return 0; 220 } 221 222 return 0; 223 } 224