subrata_modak | 88af335 | 2008-11-27 15:33:55 +0000 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (c) International Business Machines Corp., 2007 |
| 3 | * This program is free software; you can redistribute it and/or modify |
| 4 | * it under the terms of the GNU General Public License as published by |
| 5 | * the Free Software Foundation; either version 2 of the License, or |
| 6 | * (at your option) any later version. |
| 7 | * This program is distributed in the hope that it will be useful |
| 8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See |
| 10 | * the GNU General Public License for more details. |
| 11 | * You should have received a copy of the GNU General Public License |
| 12 | * along with this program; if not, write to the Free Software |
Wanlong Gao | 4548c6c | 2012-10-19 18:03:36 +0800 | [diff] [blame] | 13 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
subrata_modak | 88af335 | 2008-11-27 15:33:55 +0000 | [diff] [blame] | 14 | * |
| 15 | *************************************************************************** |
| 16 | * |
| 17 | * Assertion: |
| 18 | * a) Create a container. |
| 19 | * b) Create many levels of child containers inside this container. |
| 20 | * c) Now do kill -9 init , outside of the container. |
| 21 | * d) This should kill all the child containers. |
| 22 | * (containers created at the level below) |
| 23 | * |
| 24 | * Description: |
| 25 | * 1. Parent process clone a process with flag CLONE_NEWPID |
| 26 | * 2. The container will recursively loop and creates 4 more containers. |
| 27 | * 3. All the container init's goes into sleep(), waiting to be terminated. |
| 28 | * 4. The parent process will kill child[3] by passing SIGKILL |
| 29 | * 5. Now parent process, verifies the child containers 4 & 5 are destroyed. |
| 30 | * 6. If they are killed then |
Garrett Cooper | ad14e90 | 2010-12-16 10:03:44 -0800 | [diff] [blame] | 31 | * Test passed |
| 32 | * else Test failed. |
subrata_modak | 88af335 | 2008-11-27 15:33:55 +0000 | [diff] [blame] | 33 | * |
| 34 | * Test Name: pidns05 |
| 35 | * |
| 36 | * History: |
| 37 | * |
Monson Shao | 4519224 | 2013-01-08 11:34:44 +0800 | [diff] [blame] | 38 | * FLAG DATE NAME DESCRIPTION |
| 39 | * 31/10/08 Veerendra C <vechandr@in.ibm.com> Verifies killing of NestedCont's |
subrata_modak | 88af335 | 2008-11-27 15:33:55 +0000 | [diff] [blame] | 40 | * |
| 41 | *******************************************************************************/ |
| 42 | #define _GNU_SOURCE 1 |
| 43 | #include <sys/wait.h> |
| 44 | #include <assert.h> |
| 45 | #include <stdio.h> |
| 46 | #include <stdlib.h> |
| 47 | #include <unistd.h> |
| 48 | #include <string.h> |
| 49 | #include <errno.h> |
Garrett Cooper | e8530df | 2010-12-21 11:37:57 -0800 | [diff] [blame] | 50 | #include "test.h" |
subrata_modak | 88af335 | 2008-11-27 15:33:55 +0000 | [diff] [blame] | 51 | #include <libclone.h> |
Jan Stancek | ed991ae | 2014-07-29 10:50:27 +0200 | [diff] [blame] | 52 | #include "pidns_helper.h" |
subrata_modak | 88af335 | 2008-11-27 15:33:55 +0000 | [diff] [blame] | 53 | |
| 54 | #define INIT_PID 1 |
| 55 | #define CINIT_PID 1 |
| 56 | #define PARENT_PID 0 |
| 57 | #define MAX_DEPTH 5 |
| 58 | |
| 59 | char *TCID = "pidns05"; |
| 60 | int TST_TOTAL = 1; |
| 61 | int fd[2]; |
| 62 | |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 63 | void cleanup(void) |
subrata_modak | 88af335 | 2008-11-27 15:33:55 +0000 | [diff] [blame] | 64 | { |
subrata_modak | 88af335 | 2008-11-27 15:33:55 +0000 | [diff] [blame] | 65 | } |
Garrett Cooper | ad14e90 | 2010-12-16 10:03:44 -0800 | [diff] [blame] | 66 | |
| 67 | int max_pid(void) |
subrata_modak | 88af335 | 2008-11-27 15:33:55 +0000 | [diff] [blame] | 68 | { |
| 69 | FILE *fp; |
| 70 | int ret; |
| 71 | |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 72 | fp = fopen("/proc/sys/kernel/pid_max", "r"); |
subrata_modak | 88af335 | 2008-11-27 15:33:55 +0000 | [diff] [blame] | 73 | if (fp != NULL) { |
| 74 | fscanf(fp, "%d", &ret); |
| 75 | fclose(fp); |
| 76 | } else { |
Monson Shao | 4519224 | 2013-01-08 11:34:44 +0800 | [diff] [blame] | 77 | tst_resm(TBROK, "Cannot open /proc/sys/kernel/pid_max"); |
subrata_modak | 88af335 | 2008-11-27 15:33:55 +0000 | [diff] [blame] | 78 | ret = -1; |
| 79 | } |
| 80 | return ret; |
| 81 | } |
| 82 | |
| 83 | /* find_cinit_pids() iteratively finds the pid's having same PGID as its parent. |
| 84 | * Input parameter - Accepts pointer to pid_t : To copy the pid's matching. |
| 85 | * Returns - the number of pids matched. |
| 86 | */ |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 87 | int find_cinit_pids(pid_t * pids) |
subrata_modak | 88af335 | 2008-11-27 15:33:55 +0000 | [diff] [blame] | 88 | { |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 89 | int next = 0, pid_max, i; |
subrata_modak | 88af335 | 2008-11-27 15:33:55 +0000 | [diff] [blame] | 90 | pid_t parentpid, pgid, pgid2; |
| 91 | |
| 92 | pid_max = max_pid(); |
| 93 | parentpid = getpid(); |
| 94 | pgid = getpgid(parentpid); |
| 95 | |
| 96 | /* The loop breaks, when the loop counter reaches the parentpid value */ |
| 97 | for (i = parentpid + 1; i != parentpid; i++) { |
| 98 | if (i > pid_max) |
| 99 | i = 2; |
| 100 | |
| 101 | pgid2 = getpgid(i); |
| 102 | if (pgid2 == pgid) { |
| 103 | pids[next] = i; |
| 104 | next++; |
| 105 | } |
| 106 | } |
| 107 | return next; |
| 108 | } |
| 109 | |
| 110 | /* |
| 111 | * create_nested_container() Recursively create MAX_DEPTH nested containers |
| 112 | */ |
| 113 | int create_nested_container(void *vtest) |
| 114 | { |
Garrett Cooper | ad14e90 | 2010-12-16 10:03:44 -0800 | [diff] [blame] | 115 | int exit_val; |
| 116 | int ret, count, *level; |
subrata_modak | 88af335 | 2008-11-27 15:33:55 +0000 | [diff] [blame] | 117 | pid_t cpid, ppid; |
| 118 | cpid = getpid(); |
| 119 | ppid = getppid(); |
| 120 | char mesg[] = "Nested Containers are created"; |
| 121 | |
| 122 | level = (int *)vtest; |
| 123 | count = *level; |
| 124 | |
| 125 | /* Child process closes up read side of pipe */ |
| 126 | close(fd[0]); |
| 127 | |
| 128 | /* Comparing the values to make sure pidns is created correctly */ |
Garrett Cooper | ad14e90 | 2010-12-16 10:03:44 -0800 | [diff] [blame] | 129 | if (cpid != CINIT_PID || ppid != PARENT_PID) { |
| 130 | printf("Got unexpected cpid and/or ppid (cpid=%d ppid=%d)\n", |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 131 | cpid, ppid); |
Garrett Cooper | ad14e90 | 2010-12-16 10:03:44 -0800 | [diff] [blame] | 132 | exit_val = 1; |
subrata_modak | 88af335 | 2008-11-27 15:33:55 +0000 | [diff] [blame] | 133 | } |
| 134 | if (count > 1) { |
| 135 | count--; |
| 136 | ret = do_clone_unshare_test(T_CLONE, CLONE_NEWPID, |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 137 | create_nested_container, |
| 138 | (void *)&count); |
subrata_modak | 88af335 | 2008-11-27 15:33:55 +0000 | [diff] [blame] | 139 | if (ret == -1) { |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 140 | printf("clone failed; errno = %d : %s\n", |
| 141 | ret, strerror(ret)); |
Garrett Cooper | ad14e90 | 2010-12-16 10:03:44 -0800 | [diff] [blame] | 142 | exit_val = 1; |
| 143 | } else |
| 144 | exit_val = 0; |
subrata_modak | 88af335 | 2008-11-27 15:33:55 +0000 | [diff] [blame] | 145 | } else { |
| 146 | /* Sending mesg, 'Nested containers created' through the pipe */ |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 147 | write(fd[1], mesg, (strlen(mesg) + 1)); |
Garrett Cooper | ad14e90 | 2010-12-16 10:03:44 -0800 | [diff] [blame] | 148 | exit_val = 0; |
subrata_modak | 88af335 | 2008-11-27 15:33:55 +0000 | [diff] [blame] | 149 | } |
| 150 | |
| 151 | close(fd[1]); |
| 152 | pause(); |
| 153 | |
Garrett Cooper | ad14e90 | 2010-12-16 10:03:44 -0800 | [diff] [blame] | 154 | return exit_val; |
subrata_modak | 88af335 | 2008-11-27 15:33:55 +0000 | [diff] [blame] | 155 | } |
| 156 | |
subrata_modak | 88af335 | 2008-11-27 15:33:55 +0000 | [diff] [blame] | 157 | void kill_nested_containers() |
| 158 | { |
| 159 | int orig_count, new_count, status = 0, i; |
| 160 | pid_t pids[MAX_DEPTH]; |
| 161 | pid_t pids_new[MAX_DEPTH]; |
| 162 | |
| 163 | orig_count = find_cinit_pids(pids); |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 164 | kill(pids[MAX_DEPTH - 3], SIGKILL); |
subrata_modak | 88af335 | 2008-11-27 15:33:55 +0000 | [diff] [blame] | 165 | sleep(1); |
| 166 | |
| 167 | /* After killing child container, getting the New PID list */ |
| 168 | new_count = find_cinit_pids(pids_new); |
| 169 | |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 170 | /* Verifying that the child containers were destroyed when parent is killed */ |
subrata_modak | 88af335 | 2008-11-27 15:33:55 +0000 | [diff] [blame] | 171 | if (orig_count - 2 != new_count) |
| 172 | status = -1; |
| 173 | |
| 174 | for (i = 0; i < new_count; i++) { |
| 175 | if (pids[i] != pids_new[i]) |
| 176 | status = -1; |
| 177 | } |
| 178 | |
| 179 | if (status == 0) |
Monson Shao | 4519224 | 2013-01-08 11:34:44 +0800 | [diff] [blame] | 180 | tst_resm(TPASS, "The number of containers killed are %d", |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 181 | orig_count - new_count); |
subrata_modak | 88af335 | 2008-11-27 15:33:55 +0000 | [diff] [blame] | 182 | else |
| 183 | tst_resm(TFAIL, "Failed to kill the sub-containers of " |
Monson Shao | 4519224 | 2013-01-08 11:34:44 +0800 | [diff] [blame] | 184 | "the container %d", pids[MAX_DEPTH - 3]); |
subrata_modak | 88af335 | 2008-11-27 15:33:55 +0000 | [diff] [blame] | 185 | |
Garrett Cooper | ad14e90 | 2010-12-16 10:03:44 -0800 | [diff] [blame] | 186 | /* Loops through the containers created to exit from sleep() */ |
subrata_modak | 88af335 | 2008-11-27 15:33:55 +0000 | [diff] [blame] | 187 | for (i = 0; i < MAX_DEPTH; i++) { |
Peng Haitao | 02fa930 | 2011-04-04 10:45:40 +0800 | [diff] [blame] | 188 | kill(pids[i], SIGKILL); |
| 189 | waitpid(pids[i], &status, 0); |
subrata_modak | 88af335 | 2008-11-27 15:33:55 +0000 | [diff] [blame] | 190 | } |
| 191 | } |
| 192 | |
Jan Stancek | ed991ae | 2014-07-29 10:50:27 +0200 | [diff] [blame] | 193 | static void setup(void) |
| 194 | { |
| 195 | tst_require_root(NULL); |
| 196 | check_newpid(); |
| 197 | } |
| 198 | |
subrata_modak | 88af335 | 2008-11-27 15:33:55 +0000 | [diff] [blame] | 199 | int main(int argc, char *argv[]) |
| 200 | { |
| 201 | int ret, nbytes, status; |
| 202 | char readbuffer[80]; |
| 203 | pid_t pid, pgid; |
| 204 | int count = MAX_DEPTH; |
| 205 | |
Jan Stancek | ed991ae | 2014-07-29 10:50:27 +0200 | [diff] [blame] | 206 | setup(); |
| 207 | |
Garrett Cooper | 1e6f5a6 | 2010-12-19 09:58:10 -0800 | [diff] [blame] | 208 | /* |
Garrett Cooper | ad14e90 | 2010-12-16 10:03:44 -0800 | [diff] [blame] | 209 | * XXX (garrcoop): why in the hell is this fork-wait written this way? |
| 210 | * This doesn't add up with the pattern used for the rest of the tests, |
| 211 | * so I'm pretty damn sure this test is written incorrectly. |
| 212 | */ |
subrata_modak | 88af335 | 2008-11-27 15:33:55 +0000 | [diff] [blame] | 213 | pid = fork(); |
Garrett Cooper | ad14e90 | 2010-12-16 10:03:44 -0800 | [diff] [blame] | 214 | if (pid == -1) { |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 215 | tst_brkm(TBROK | TERRNO, NULL, "fork failed"); |
Garrett Cooper | ad14e90 | 2010-12-16 10:03:44 -0800 | [diff] [blame] | 216 | } else if (pid != 0) { |
| 217 | /* |
| 218 | * NOTE: use waitpid so that we know we're waiting for the |
| 219 | * _top-level_ child instead of a spawned subcontainer. |
| 220 | * |
| 221 | * XXX (garrcoop): Might want to mask SIGCHLD in the top-level |
| 222 | * child too, or not *shrugs*. |
| 223 | */ |
| 224 | if (waitpid(pid, &status, 0) == -1) { |
| 225 | perror("wait failed"); |
| 226 | } |
Peng Haitao | 02fa930 | 2011-04-04 10:45:40 +0800 | [diff] [blame] | 227 | if (WIFEXITED(status)) |
| 228 | exit(WEXITSTATUS(status)); |
| 229 | else |
| 230 | exit(status); |
subrata_modak | 88af335 | 2008-11-27 15:33:55 +0000 | [diff] [blame] | 231 | } |
| 232 | |
| 233 | /* To make all the containers share the same PGID as its parent */ |
| 234 | setpgid(0, 0); |
| 235 | |
| 236 | pid = getpid(); |
| 237 | pgid = getpgid(pid); |
| 238 | ret = pipe(fd); |
| 239 | if (ret == -1) |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 240 | tst_brkm(TBROK | TERRNO, cleanup, "pipe failed"); |
subrata_modak | 88af335 | 2008-11-27 15:33:55 +0000 | [diff] [blame] | 241 | |
Garrett Cooper | ad14e90 | 2010-12-16 10:03:44 -0800 | [diff] [blame] | 242 | TEST(do_clone_unshare_test(T_CLONE, CLONE_NEWPID, |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 243 | create_nested_container, (void *)&count)); |
Garrett Cooper | ad14e90 | 2010-12-16 10:03:44 -0800 | [diff] [blame] | 244 | if (TEST_RETURN == -1) { |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 245 | tst_brkm(TFAIL | TTERRNO, cleanup, "clone failed"); |
subrata_modak | 88af335 | 2008-11-27 15:33:55 +0000 | [diff] [blame] | 246 | } |
| 247 | |
| 248 | close(fd[1]); |
| 249 | /* Waiting for the MAX_DEPTH number of containers to be created */ |
| 250 | nbytes = read(fd[0], readbuffer, sizeof(readbuffer)); |
| 251 | close(fd[0]); |
| 252 | if (nbytes > 0) |
| 253 | tst_resm(TINFO, " %d %s", MAX_DEPTH, readbuffer); |
Garrett Cooper | ad14e90 | 2010-12-16 10:03:44 -0800 | [diff] [blame] | 254 | else |
| 255 | tst_brkm(TFAIL, cleanup, "unable to create %d containers", |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 256 | MAX_DEPTH); |
subrata_modak | 88af335 | 2008-11-27 15:33:55 +0000 | [diff] [blame] | 257 | |
Garrett Cooper | ad14e90 | 2010-12-16 10:03:44 -0800 | [diff] [blame] | 258 | /* Kill the container created */ |
subrata_modak | 88af335 | 2008-11-27 15:33:55 +0000 | [diff] [blame] | 259 | kill_nested_containers(); |
subrata_modak | 88af335 | 2008-11-27 15:33:55 +0000 | [diff] [blame] | 260 | cleanup(); |
| 261 | |
Garrett Cooper | 2c28215 | 2010-12-16 00:55:50 -0800 | [diff] [blame] | 262 | tst_exit(); |
Peng Haitao | 02fa930 | 2011-04-04 10:45:40 +0800 | [diff] [blame] | 263 | } |