test_kill.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  1. /* SPDX-License-Identifier: GPL-2.0 */
  2. #include <errno.h>
  3. #include <linux/limits.h>
  4. #include <stdbool.h>
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <string.h>
  8. #include <sys/types.h>
  9. #include <unistd.h>
  10. #include "../kselftest.h"
  11. #include "../pidfd/pidfd.h"
  12. #include "cgroup_util.h"
  13. /*
  14. * Kill the given cgroup and wait for the inotify signal.
  15. * If there are no events in 10 seconds, treat this as an error.
  16. * Then check that the cgroup is in the desired state.
  17. */
  18. static int cg_kill_wait(const char *cgroup)
  19. {
  20. int fd, ret = -1;
  21. fd = cg_prepare_for_wait(cgroup);
  22. if (fd < 0)
  23. return fd;
  24. ret = cg_write(cgroup, "cgroup.kill", "1");
  25. if (ret)
  26. goto out;
  27. ret = cg_wait_for(fd);
  28. if (ret)
  29. goto out;
  30. out:
  31. close(fd);
  32. return ret;
  33. }
  34. /*
  35. * A simple process running in a sleep loop until being
  36. * re-parented.
  37. */
  38. static int child_fn(const char *cgroup, void *arg)
  39. {
  40. int ppid = getppid();
  41. while (getppid() == ppid)
  42. usleep(1000);
  43. return getppid() == ppid;
  44. }
  45. static int test_cgkill_simple(const char *root)
  46. {
  47. pid_t pids[100];
  48. int ret = KSFT_FAIL;
  49. char *cgroup = NULL;
  50. int i;
  51. cgroup = cg_name(root, "cg_test_simple");
  52. if (!cgroup)
  53. goto cleanup;
  54. if (cg_create(cgroup))
  55. goto cleanup;
  56. for (i = 0; i < 100; i++)
  57. pids[i] = cg_run_nowait(cgroup, child_fn, NULL);
  58. if (cg_wait_for_proc_count(cgroup, 100))
  59. goto cleanup;
  60. if (cg_read_strcmp(cgroup, "cgroup.events", "populated 1\n"))
  61. goto cleanup;
  62. if (cg_kill_wait(cgroup))
  63. goto cleanup;
  64. ret = KSFT_PASS;
  65. cleanup:
  66. for (i = 0; i < 100; i++)
  67. wait_for_pid(pids[i]);
  68. if (ret == KSFT_PASS &&
  69. cg_read_strcmp(cgroup, "cgroup.events", "populated 0\n"))
  70. ret = KSFT_FAIL;
  71. if (cgroup)
  72. cg_destroy(cgroup);
  73. free(cgroup);
  74. return ret;
  75. }
  76. /*
  77. * The test creates the following hierarchy:
  78. * A
  79. * / / \ \
  80. * B E I K
  81. * /\ |
  82. * C D F
  83. * |
  84. * G
  85. * |
  86. * H
  87. *
  88. * with a process in C, H and 3 processes in K.
  89. * Then it tries to kill the whole tree.
  90. */
  91. static int test_cgkill_tree(const char *root)
  92. {
  93. pid_t pids[5];
  94. char *cgroup[10] = {0};
  95. int ret = KSFT_FAIL;
  96. int i;
  97. cgroup[0] = cg_name(root, "cg_test_tree_A");
  98. if (!cgroup[0])
  99. goto cleanup;
  100. cgroup[1] = cg_name(cgroup[0], "B");
  101. if (!cgroup[1])
  102. goto cleanup;
  103. cgroup[2] = cg_name(cgroup[1], "C");
  104. if (!cgroup[2])
  105. goto cleanup;
  106. cgroup[3] = cg_name(cgroup[1], "D");
  107. if (!cgroup[3])
  108. goto cleanup;
  109. cgroup[4] = cg_name(cgroup[0], "E");
  110. if (!cgroup[4])
  111. goto cleanup;
  112. cgroup[5] = cg_name(cgroup[4], "F");
  113. if (!cgroup[5])
  114. goto cleanup;
  115. cgroup[6] = cg_name(cgroup[5], "G");
  116. if (!cgroup[6])
  117. goto cleanup;
  118. cgroup[7] = cg_name(cgroup[6], "H");
  119. if (!cgroup[7])
  120. goto cleanup;
  121. cgroup[8] = cg_name(cgroup[0], "I");
  122. if (!cgroup[8])
  123. goto cleanup;
  124. cgroup[9] = cg_name(cgroup[0], "K");
  125. if (!cgroup[9])
  126. goto cleanup;
  127. for (i = 0; i < 10; i++)
  128. if (cg_create(cgroup[i]))
  129. goto cleanup;
  130. pids[0] = cg_run_nowait(cgroup[2], child_fn, NULL);
  131. pids[1] = cg_run_nowait(cgroup[7], child_fn, NULL);
  132. pids[2] = cg_run_nowait(cgroup[9], child_fn, NULL);
  133. pids[3] = cg_run_nowait(cgroup[9], child_fn, NULL);
  134. pids[4] = cg_run_nowait(cgroup[9], child_fn, NULL);
  135. /*
  136. * Wait until all child processes will enter
  137. * corresponding cgroups.
  138. */
  139. if (cg_wait_for_proc_count(cgroup[2], 1) ||
  140. cg_wait_for_proc_count(cgroup[7], 1) ||
  141. cg_wait_for_proc_count(cgroup[9], 3))
  142. goto cleanup;
  143. /*
  144. * Kill A and check that we get an empty notification.
  145. */
  146. if (cg_kill_wait(cgroup[0]))
  147. goto cleanup;
  148. ret = KSFT_PASS;
  149. cleanup:
  150. for (i = 0; i < 5; i++)
  151. wait_for_pid(pids[i]);
  152. if (ret == KSFT_PASS &&
  153. cg_read_strcmp(cgroup[0], "cgroup.events", "populated 0\n"))
  154. ret = KSFT_FAIL;
  155. for (i = 9; i >= 0 && cgroup[i]; i--) {
  156. cg_destroy(cgroup[i]);
  157. free(cgroup[i]);
  158. }
  159. return ret;
  160. }
  161. static int forkbomb_fn(const char *cgroup, void *arg)
  162. {
  163. int ppid;
  164. fork();
  165. fork();
  166. ppid = getppid();
  167. while (getppid() == ppid)
  168. usleep(1000);
  169. return getppid() == ppid;
  170. }
  171. /*
  172. * The test runs a fork bomb in a cgroup and tries to kill it.
  173. */
  174. static int test_cgkill_forkbomb(const char *root)
  175. {
  176. int ret = KSFT_FAIL;
  177. char *cgroup = NULL;
  178. pid_t pid = -ESRCH;
  179. cgroup = cg_name(root, "cg_forkbomb_test");
  180. if (!cgroup)
  181. goto cleanup;
  182. if (cg_create(cgroup))
  183. goto cleanup;
  184. pid = cg_run_nowait(cgroup, forkbomb_fn, NULL);
  185. if (pid < 0)
  186. goto cleanup;
  187. usleep(100000);
  188. if (cg_kill_wait(cgroup))
  189. goto cleanup;
  190. if (cg_wait_for_proc_count(cgroup, 0))
  191. goto cleanup;
  192. ret = KSFT_PASS;
  193. cleanup:
  194. if (pid > 0)
  195. wait_for_pid(pid);
  196. if (ret == KSFT_PASS &&
  197. cg_read_strcmp(cgroup, "cgroup.events", "populated 0\n"))
  198. ret = KSFT_FAIL;
  199. if (cgroup)
  200. cg_destroy(cgroup);
  201. free(cgroup);
  202. return ret;
  203. }
  204. #define T(x) { x, #x }
  205. struct cgkill_test {
  206. int (*fn)(const char *root);
  207. const char *name;
  208. } tests[] = {
  209. T(test_cgkill_simple),
  210. T(test_cgkill_tree),
  211. T(test_cgkill_forkbomb),
  212. };
  213. #undef T
  214. int main(int argc, char *argv[])
  215. {
  216. char root[PATH_MAX];
  217. int i, ret = EXIT_SUCCESS;
  218. if (cg_find_unified_root(root, sizeof(root)))
  219. ksft_exit_skip("cgroup v2 isn't mounted\n");
  220. for (i = 0; i < ARRAY_SIZE(tests); i++) {
  221. switch (tests[i].fn(root)) {
  222. case KSFT_PASS:
  223. ksft_test_result_pass("%s\n", tests[i].name);
  224. break;
  225. case KSFT_SKIP:
  226. ksft_test_result_skip("%s\n", tests[i].name);
  227. break;
  228. default:
  229. ret = EXIT_FAILURE;
  230. ksft_test_result_fail("%s\n", tests[i].name);
  231. break;
  232. }
  233. }
  234. return ret;
  235. }