| // SPDX-License-Identifier: GPL-2.0 |
| /* Copyright (c) 2022 Meta Platforms, Inc. and affiliates. */ |
| |
| #include <vmlinux.h> |
| #include <bpf/bpf_tracing.h> |
| #include <bpf/bpf_helpers.h> |
| |
| #include "cgrp_kfunc_common.h" |
| |
| char _license[] SEC("license") = "GPL"; |
| |
| int err, pid, invocations; |
| |
| /* Prototype for all of the program trace events below: |
| * |
| * TRACE_EVENT(cgroup_mkdir, |
| * TP_PROTO(struct cgroup *cgrp, const char *path), |
| * TP_ARGS(cgrp, path) |
| */ |
| |
| static bool is_test_kfunc_task(void) |
| { |
| int cur_pid = bpf_get_current_pid_tgid() >> 32; |
| bool same = pid == cur_pid; |
| |
| if (same) |
| __sync_fetch_and_add(&invocations, 1); |
| |
| return same; |
| } |
| |
| SEC("tp_btf/cgroup_mkdir") |
| int BPF_PROG(test_cgrp_acquire_release_argument, struct cgroup *cgrp, const char *path) |
| { |
| struct cgroup *acquired; |
| |
| if (!is_test_kfunc_task()) |
| return 0; |
| |
| acquired = bpf_cgroup_acquire(cgrp); |
| if (!acquired) |
| err = 1; |
| else |
| bpf_cgroup_release(acquired); |
| |
| return 0; |
| } |
| |
| SEC("tp_btf/cgroup_mkdir") |
| int BPF_PROG(test_cgrp_acquire_leave_in_map, struct cgroup *cgrp, const char *path) |
| { |
| long status; |
| |
| if (!is_test_kfunc_task()) |
| return 0; |
| |
| status = cgrps_kfunc_map_insert(cgrp); |
| if (status) |
| err = 1; |
| |
| return 0; |
| } |
| |
| SEC("tp_btf/cgroup_mkdir") |
| int BPF_PROG(test_cgrp_xchg_release, struct cgroup *cgrp, const char *path) |
| { |
| struct cgroup *kptr, *cg; |
| struct __cgrps_kfunc_map_value *v; |
| long status; |
| |
| if (!is_test_kfunc_task()) |
| return 0; |
| |
| status = cgrps_kfunc_map_insert(cgrp); |
| if (status) { |
| err = 1; |
| return 0; |
| } |
| |
| v = cgrps_kfunc_map_value_lookup(cgrp); |
| if (!v) { |
| err = 2; |
| return 0; |
| } |
| |
| kptr = v->cgrp; |
| if (!kptr) { |
| err = 4; |
| return 0; |
| } |
| |
| cg = bpf_cgroup_ancestor(kptr, 1); |
| if (cg) /* verifier only check */ |
| bpf_cgroup_release(cg); |
| |
| kptr = bpf_kptr_xchg(&v->cgrp, NULL); |
| if (!kptr) { |
| err = 3; |
| return 0; |
| } |
| |
| bpf_cgroup_release(kptr); |
| |
| return 0; |
| } |
| |
| SEC("tp_btf/cgroup_mkdir") |
| int BPF_PROG(test_cgrp_get_release, struct cgroup *cgrp, const char *path) |
| { |
| struct cgroup *kptr; |
| struct __cgrps_kfunc_map_value *v; |
| long status; |
| |
| if (!is_test_kfunc_task()) |
| return 0; |
| |
| status = cgrps_kfunc_map_insert(cgrp); |
| if (status) { |
| err = 1; |
| return 0; |
| } |
| |
| v = cgrps_kfunc_map_value_lookup(cgrp); |
| if (!v) { |
| err = 2; |
| return 0; |
| } |
| |
| bpf_rcu_read_lock(); |
| kptr = v->cgrp; |
| if (!kptr) |
| err = 3; |
| bpf_rcu_read_unlock(); |
| |
| return 0; |
| } |
| |
| SEC("tp_btf/cgroup_mkdir") |
| int BPF_PROG(test_cgrp_get_ancestors, struct cgroup *cgrp, const char *path) |
| { |
| struct cgroup *self, *ancestor1, *invalid; |
| |
| if (!is_test_kfunc_task()) |
| return 0; |
| |
| self = bpf_cgroup_ancestor(cgrp, cgrp->level); |
| if (!self) { |
| err = 1; |
| return 0; |
| } |
| |
| if (self->self.id != cgrp->self.id) { |
| bpf_cgroup_release(self); |
| err = 2; |
| return 0; |
| } |
| bpf_cgroup_release(self); |
| |
| ancestor1 = bpf_cgroup_ancestor(cgrp, cgrp->level - 1); |
| if (!ancestor1) { |
| err = 3; |
| return 0; |
| } |
| bpf_cgroup_release(ancestor1); |
| |
| invalid = bpf_cgroup_ancestor(cgrp, 10000); |
| if (invalid) { |
| bpf_cgroup_release(invalid); |
| err = 4; |
| return 0; |
| } |
| |
| invalid = bpf_cgroup_ancestor(cgrp, -1); |
| if (invalid) { |
| bpf_cgroup_release(invalid); |
| err = 5; |
| return 0; |
| } |
| |
| return 0; |
| } |
| |
| SEC("tp_btf/cgroup_mkdir") |
| int BPF_PROG(test_cgrp_from_id, struct cgroup *cgrp, const char *path) |
| { |
| struct cgroup *parent, *res; |
| u64 parent_cgid; |
| |
| if (!is_test_kfunc_task()) |
| return 0; |
| |
| /* @cgrp's ID is not visible yet, let's test with the parent */ |
| parent = bpf_cgroup_ancestor(cgrp, cgrp->level - 1); |
| if (!parent) { |
| err = 1; |
| return 0; |
| } |
| |
| parent_cgid = parent->kn->id; |
| bpf_cgroup_release(parent); |
| |
| res = bpf_cgroup_from_id(parent_cgid); |
| if (!res) { |
| err = 2; |
| return 0; |
| } |
| |
| bpf_cgroup_release(res); |
| |
| if (res != parent) { |
| err = 3; |
| return 0; |
| } |
| |
| res = bpf_cgroup_from_id((u64)-1); |
| if (res) { |
| bpf_cgroup_release(res); |
| err = 4; |
| return 0; |
| } |
| |
| return 0; |
| } |