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