// 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; }