1 /* SPDX-License-Identifier: GPL-2.0 */ 2 3 #include <errno.h> 4 #include <linux/limits.h> 5 #include <stdbool.h> 6 #include <stdio.h> 7 #include <stdlib.h> 8 #include <string.h> 9 #include <sys/types.h> 10 #include <sys/wait.h> 11 #include <unistd.h> 12 13 #include "kselftest.h" 14 #include "../pidfd/pidfd.h" 15 #include "cgroup_util.h" 16 17 /* 18 * Kill the given cgroup and wait for the inotify signal. 19 * If there are no events in 10 seconds, treat this as an error. 20 * Then check that the cgroup is in the desired state. 21 */ 22 static int cg_kill_wait(const char *cgroup) 23 { 24 int fd, ret = -1; 25 26 fd = cg_prepare_for_wait(cgroup); 27 if (fd < 0) 28 return fd; 29 30 ret = cg_write(cgroup, "cgroup.kill", "1"); 31 if (ret) 32 goto out; 33 34 ret = cg_wait_for(fd); 35 if (ret) 36 goto out; 37 38 out: 39 close(fd); 40 return ret; 41 } 42 43 /* 44 * A simple process running in a sleep loop until being 45 * re-parented. 46 */ 47 static int child_fn(const char *cgroup, void *arg) 48 { 49 int ppid = getppid(); 50 51 while (getppid() == ppid) 52 usleep(1000); 53 54 return getppid() == ppid; 55 } 56 57 static int test_cgkill_simple(const char *root) 58 { 59 pid_t pids[100]; 60 int ret = KSFT_FAIL; 61 char *cgroup = NULL; 62 int i; 63 64 cgroup = cg_name(root, "cg_test_simple"); 65 if (!cgroup) 66 goto cleanup; 67 68 if (cg_create(cgroup)) 69 goto cleanup; 70 71 for (i = 0; i < 100; i++) 72 pids[i] = cg_run_nowait(cgroup, child_fn, NULL); 73 74 if (cg_wait_for_proc_count(cgroup, 100)) 75 goto cleanup; 76 77 if (cg_read_strcmp(cgroup, "cgroup.events", "populated 1\n")) 78 goto cleanup; 79 80 if (cg_kill_wait(cgroup)) 81 goto cleanup; 82 83 ret = KSFT_PASS; 84 85 cleanup: 86 for (i = 0; i < 100; i++) 87 wait_for_pid(pids[i]); 88 89 if (ret == KSFT_PASS && 90 cg_read_strcmp_wait(cgroup, "cgroup.events", "populated 0\n")) 91 ret = KSFT_FAIL; 92 93 if (cgroup) 94 cg_destroy(cgroup); 95 free(cgroup); 96 return ret; 97 } 98 99 /* 100 * The test creates the following hierarchy: 101 * A 102 * / / \ \ 103 * B E I K 104 * /\ | 105 * C D F 106 * | 107 * G 108 * | 109 * H 110 * 111 * with a process in C, H and 3 processes in K. 112 * Then it tries to kill the whole tree. 113 */ 114 static int test_cgkill_tree(const char *root) 115 { 116 pid_t pids[5]; 117 char *cgroup[10] = {0}; 118 int ret = KSFT_FAIL; 119 int i; 120 121 cgroup[0] = cg_name(root, "cg_test_tree_A"); 122 if (!cgroup[0]) 123 goto cleanup; 124 125 cgroup[1] = cg_name(cgroup[0], "B"); 126 if (!cgroup[1]) 127 goto cleanup; 128 129 cgroup[2] = cg_name(cgroup[1], "C"); 130 if (!cgroup[2]) 131 goto cleanup; 132 133 cgroup[3] = cg_name(cgroup[1], "D"); 134 if (!cgroup[3]) 135 goto cleanup; 136 137 cgroup[4] = cg_name(cgroup[0], "E"); 138 if (!cgroup[4]) 139 goto cleanup; 140 141 cgroup[5] = cg_name(cgroup[4], "F"); 142 if (!cgroup[5]) 143 goto cleanup; 144 145 cgroup[6] = cg_name(cgroup[5], "G"); 146 if (!cgroup[6]) 147 goto cleanup; 148 149 cgroup[7] = cg_name(cgroup[6], "H"); 150 if (!cgroup[7]) 151 goto cleanup; 152 153 cgroup[8] = cg_name(cgroup[0], "I"); 154 if (!cgroup[8]) 155 goto cleanup; 156 157 cgroup[9] = cg_name(cgroup[0], "K"); 158 if (!cgroup[9]) 159 goto cleanup; 160 161 for (i = 0; i < 10; i++) 162 if (cg_create(cgroup[i])) 163 goto cleanup; 164 165 pids[0] = cg_run_nowait(cgroup[2], child_fn, NULL); 166 pids[1] = cg_run_nowait(cgroup[7], child_fn, NULL); 167 pids[2] = cg_run_nowait(cgroup[9], child_fn, NULL); 168 pids[3] = cg_run_nowait(cgroup[9], child_fn, NULL); 169 pids[4] = cg_run_nowait(cgroup[9], child_fn, NULL); 170 171 /* 172 * Wait until all child processes will enter 173 * corresponding cgroups. 174 */ 175 176 if (cg_wait_for_proc_count(cgroup[2], 1) || 177 cg_wait_for_proc_count(cgroup[7], 1) || 178 cg_wait_for_proc_count(cgroup[9], 3)) 179 goto cleanup; 180 181 /* 182 * Kill A and check that we get an empty notification. 183 */ 184 if (cg_kill_wait(cgroup[0])) 185 goto cleanup; 186 187 ret = KSFT_PASS; 188 189 cleanup: 190 for (i = 0; i < 5; i++) 191 wait_for_pid(pids[i]); 192 193 if (ret == KSFT_PASS && 194 cg_read_strcmp_wait(cgroup[0], "cgroup.events", 195 "populated 0\n")) 196 ret = KSFT_FAIL; 197 198 for (i = 9; i >= 0 && cgroup[i]; i--) { 199 cg_destroy(cgroup[i]); 200 free(cgroup[i]); 201 } 202 203 return ret; 204 } 205 206 static int forkbomb_fn(const char *cgroup, void *arg) 207 { 208 int ppid; 209 210 fork(); 211 fork(); 212 213 ppid = getppid(); 214 215 while (getppid() == ppid) 216 usleep(1000); 217 218 return getppid() == ppid; 219 } 220 221 /* 222 * The test runs a fork bomb in a cgroup and tries to kill it. 223 */ 224 static int test_cgkill_forkbomb(const char *root) 225 { 226 int ret = KSFT_FAIL; 227 char *cgroup = NULL; 228 pid_t pid = -ESRCH; 229 230 cgroup = cg_name(root, "cg_forkbomb_test"); 231 if (!cgroup) 232 goto cleanup; 233 234 if (cg_create(cgroup)) 235 goto cleanup; 236 237 pid = cg_run_nowait(cgroup, forkbomb_fn, NULL); 238 if (pid < 0) 239 goto cleanup; 240 241 usleep(100000); 242 243 if (cg_kill_wait(cgroup)) 244 goto cleanup; 245 246 if (cg_wait_for_proc_count(cgroup, 0)) 247 goto cleanup; 248 249 ret = KSFT_PASS; 250 251 cleanup: 252 if (pid > 0) 253 wait_for_pid(pid); 254 255 if (ret == KSFT_PASS && 256 cg_read_strcmp_wait(cgroup, "cgroup.events", "populated 0\n")) 257 ret = KSFT_FAIL; 258 259 if (cgroup) 260 cg_destroy(cgroup); 261 free(cgroup); 262 return ret; 263 } 264 265 /* 266 * Test that a cgroup that was killed in the past can still be the target 267 * of clone3(CLONE_INTO_CGROUP): writing cgroup.kill must only kill the 268 * tasks in the cgroup at the time of the write, not tasks cloned into 269 * it afterwards. 270 */ 271 static int test_cgkill_clone_into_killed(const char *root) 272 { 273 pid_t pid; 274 int cgroup_fd = -EBADF; 275 int ret = KSFT_FAIL; 276 char *cgroup = NULL; 277 278 cgroup = cg_name(root, "cg_test_clone_into_killed"); 279 if (!cgroup) 280 goto cleanup; 281 282 if (cg_create(cgroup)) 283 goto cleanup; 284 285 /* Kill the cgroup while it is still empty. */ 286 if (cg_write(cgroup, "cgroup.kill", "1")) 287 goto cleanup; 288 289 cgroup_fd = dirfd_open_opath(cgroup); 290 if (cgroup_fd < 0) 291 goto cleanup; 292 293 pid = clone_into_cgroup(cgroup_fd); 294 if (pid < 0) { 295 if (errno == ENOSYS) 296 ret = KSFT_SKIP; 297 goto cleanup; 298 } 299 300 if (pid == 0) 301 exit(EXIT_SUCCESS); 302 303 /* The child must not be SIGKILLed; it has to exit cleanly. */ 304 if (clone_reap(pid, WEXITED) != EXIT_SUCCESS) 305 goto cleanup; 306 307 ret = KSFT_PASS; 308 309 cleanup: 310 if (cgroup_fd >= 0) 311 close(cgroup_fd); 312 if (cgroup) 313 cg_destroy(cgroup); 314 free(cgroup); 315 return ret; 316 } 317 318 #define T(x) { x, #x } 319 struct cgkill_test { 320 int (*fn)(const char *root); 321 const char *name; 322 } tests[] = { 323 T(test_cgkill_simple), 324 T(test_cgkill_tree), 325 T(test_cgkill_forkbomb), 326 T(test_cgkill_clone_into_killed), 327 }; 328 #undef T 329 330 int main(int argc, char *argv[]) 331 { 332 char root[PATH_MAX]; 333 int i; 334 335 ksft_print_header(); 336 if (cg_find_unified_root(root, sizeof(root), NULL)) 337 ksft_exit_skip("cgroup v2 isn't mounted\n"); 338 ksft_set_plan(ARRAY_SIZE(tests)); 339 for (i = 0; i < ARRAY_SIZE(tests); i++) { 340 switch (tests[i].fn(root)) { 341 case KSFT_PASS: 342 ksft_test_result_pass("%s\n", tests[i].name); 343 break; 344 case KSFT_SKIP: 345 ksft_test_result_skip("%s\n", tests[i].name); 346 break; 347 default: 348 ksft_test_result_fail("%s\n", tests[i].name); 349 break; 350 } 351 } 352 353 ksft_finished(); 354 } 355