1 // SPDX-License-Identifier: GPL-2.0 2 /* Copyright (c) 2022 Meta Platforms, Inc. and affiliates. */ 3 4 #define _GNU_SOURCE 5 #include <cgroup_helpers.h> 6 #include <test_progs.h> 7 #include <sched.h> 8 #include <sys/wait.h> 9 10 #include "cgrp_kfunc_failure.skel.h" 11 #include "cgrp_kfunc_success.skel.h" 12 13 static struct cgrp_kfunc_success *open_load_cgrp_kfunc_skel(void) 14 { 15 struct cgrp_kfunc_success *skel; 16 int err; 17 18 skel = cgrp_kfunc_success__open(); 19 if (!ASSERT_OK_PTR(skel, "skel_open")) 20 return NULL; 21 22 skel->bss->pid = getpid(); 23 24 err = cgrp_kfunc_success__load(skel); 25 if (!ASSERT_OK(err, "skel_load")) 26 goto cleanup; 27 28 return skel; 29 30 cleanup: 31 cgrp_kfunc_success__destroy(skel); 32 return NULL; 33 } 34 35 static int mkdir_rm_test_dir(void) 36 { 37 int fd; 38 const char *cgrp_path = "cgrp_kfunc"; 39 40 fd = create_and_get_cgroup(cgrp_path); 41 if (!ASSERT_GT(fd, 0, "mkdir_cgrp_fd")) 42 return -1; 43 44 close(fd); 45 remove_cgroup(cgrp_path); 46 47 return 0; 48 } 49 50 static void run_success_test(const char *prog_name) 51 { 52 struct cgrp_kfunc_success *skel; 53 struct bpf_program *prog; 54 struct bpf_link *link = NULL; 55 56 skel = open_load_cgrp_kfunc_skel(); 57 if (!ASSERT_OK_PTR(skel, "open_load_skel")) 58 return; 59 60 if (!ASSERT_OK(skel->bss->err, "pre_mkdir_err")) 61 goto cleanup; 62 63 prog = bpf_object__find_program_by_name(skel->obj, prog_name); 64 if (!ASSERT_OK_PTR(prog, "bpf_object__find_program_by_name")) 65 goto cleanup; 66 67 link = bpf_program__attach(prog); 68 if (!ASSERT_OK_PTR(link, "attached_link")) 69 goto cleanup; 70 71 ASSERT_EQ(skel->bss->invocations, 0, "pre_rmdir_count"); 72 if (!ASSERT_OK(mkdir_rm_test_dir(), "cgrp_mkdir")) 73 goto cleanup; 74 75 ASSERT_EQ(skel->bss->invocations, 1, "post_rmdir_count"); 76 ASSERT_OK(skel->bss->err, "post_rmdir_err"); 77 78 cleanup: 79 bpf_link__destroy(link); 80 cgrp_kfunc_success__destroy(skel); 81 } 82 83 static const char * const success_tests[] = { 84 "test_cgrp_acquire_release_argument", 85 "test_cgrp_acquire_leave_in_map", 86 "test_cgrp_xchg_release", 87 "test_cgrp_get_release", 88 "test_cgrp_get_ancestors", 89 "test_cgrp_from_id", 90 }; 91 92 static void test_cgrp_from_id_ns(void) 93 { 94 LIBBPF_OPTS(bpf_test_run_opts, opts); 95 struct cgrp_kfunc_success *skel; 96 struct bpf_program *prog; 97 int pid, pipe_fd[2]; 98 99 skel = open_load_cgrp_kfunc_skel(); 100 if (!ASSERT_OK_PTR(skel, "open_load_skel")) 101 return; 102 103 if (!ASSERT_OK(skel->bss->err, "pre_mkdir_err")) 104 goto cleanup; 105 106 prog = skel->progs.test_cgrp_from_id_ns; 107 108 if (!ASSERT_OK(pipe(pipe_fd), "pipe")) 109 goto cleanup; 110 111 pid = fork(); 112 if (!ASSERT_GE(pid, 0, "fork result")) { 113 close(pipe_fd[0]); 114 close(pipe_fd[1]); 115 goto cleanup; 116 } 117 118 if (pid == 0) { 119 int ret = 0; 120 121 close(pipe_fd[0]); 122 123 if (!ASSERT_GE(cgroup_setup_and_join("cgrp_from_id_ns"), 0, "join cgroup")) 124 exit(1); 125 126 if (!ASSERT_OK(unshare(CLONE_NEWCGROUP), "unshare cgns")) 127 exit(1); 128 129 ret = bpf_prog_test_run_opts(bpf_program__fd(prog), &opts); 130 if (!ASSERT_OK(ret, "test run ret")) 131 exit(1); 132 133 if (!ASSERT_OK(opts.retval, "test run retval")) 134 exit(1); 135 136 if (!ASSERT_EQ(write(pipe_fd[1], &ret, sizeof(ret)), sizeof(ret), "write pipe")) 137 exit(1); 138 139 exit(0); 140 } else { 141 int res; 142 143 close(pipe_fd[1]); 144 145 ASSERT_EQ(read(pipe_fd[0], &res, sizeof(res)), sizeof(res), "read res"); 146 ASSERT_EQ(waitpid(pid, NULL, 0), pid, "wait on child"); 147 148 remove_cgroup_pid("cgrp_from_id_ns", pid); 149 150 ASSERT_OK(res, "result from run"); 151 } 152 153 close(pipe_fd[0]); 154 cleanup: 155 cgrp_kfunc_success__destroy(skel); 156 } 157 158 void test_cgrp_kfunc(void) 159 { 160 int i, err; 161 162 err = setup_cgroup_environment(); 163 if (!ASSERT_OK(err, "cgrp_env_setup")) 164 goto cleanup; 165 166 for (i = 0; i < ARRAY_SIZE(success_tests); i++) { 167 if (!test__start_subtest(success_tests[i])) 168 continue; 169 170 run_success_test(success_tests[i]); 171 } 172 173 if (test__start_subtest("test_cgrp_from_id_ns")) 174 test_cgrp_from_id_ns(); 175 176 RUN_TESTS(cgrp_kfunc_failure); 177 178 cleanup: 179 cleanup_cgroup_environment(); 180 } 181