nstraz | e321981 | 2003-07-14 17:06:37 +0000 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (c) Wipro Technologies Ltd, 2002. All Rights Reserved. |
Wanlong Gao | 3dd0c6a | 2012-12-04 15:16:50 +0800 | [diff] [blame] | 3 | * Copyright (c) 2012 Wanlong Gao <gaowanlong@cn.fujitsu.com> |
nstraz | e321981 | 2003-07-14 17:06:37 +0000 | [diff] [blame] | 4 | * |
| 5 | * This program is free software; you can redistribute it and/or modify it |
| 6 | * under the terms of version 2 of the GNU General Public License as |
| 7 | * published by the Free Software Foundation. |
| 8 | * |
| 9 | * This program is distributed in the hope that it would be useful, but |
| 10 | * WITHOUT ANY WARRANTY; without even the implied warranty of |
| 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
| 12 | * |
| 13 | * You should have received a copy of the GNU General Public License along |
Wanlong Gao | fed9641 | 2012-10-24 10:10:29 +0800 | [diff] [blame] | 14 | * with this program; if not, write the Free Software Foundation, Inc., |
| 15 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
nstraz | e321981 | 2003-07-14 17:06:37 +0000 | [diff] [blame] | 16 | * |
| 17 | */ |
Wanlong Gao | 3dd0c6a | 2012-12-04 15:16:50 +0800 | [diff] [blame] | 18 | /* |
nstraz | e321981 | 2003-07-14 17:06:37 +0000 | [diff] [blame] | 19 | * TEST1 |
| 20 | * ----- |
| 21 | * Call clone() with all resources shared. |
| 22 | * |
| 23 | * CHILD: |
| 24 | * modify the shared resources |
| 25 | * return 1 on success |
| 26 | * PARENT: |
| 27 | * wait for child to finish |
| 28 | * verify that the shared resourses are modified |
| 29 | * return 1 on success |
| 30 | * If parent & child returns successfully |
| 31 | * test passed |
| 32 | * else |
| 33 | * test failed |
subrata_modak | 4bb656a | 2009-02-26 12:02:09 +0000 | [diff] [blame] | 34 | * |
nstraz | e321981 | 2003-07-14 17:06:37 +0000 | [diff] [blame] | 35 | * TEST2 |
| 36 | * ----- |
| 37 | * Call clone() with no resources shared. |
| 38 | * |
| 39 | * CHILD: |
| 40 | * modify the resources in child's address space |
| 41 | * return 1 on success |
| 42 | * PARENT: |
| 43 | * wait for child to finish |
| 44 | * verify that the parent's resourses are not modified |
| 45 | * return 1 on success |
| 46 | * If parent & child returns successfully |
| 47 | * test passed |
| 48 | * else |
| 49 | * test failed |
Wanlong Gao | 3dd0c6a | 2012-12-04 15:16:50 +0800 | [diff] [blame] | 50 | */ |
nstraz | e321981 | 2003-07-14 17:06:37 +0000 | [diff] [blame] | 51 | |
robbiew | d34d581 | 2005-07-11 22:28:09 +0000 | [diff] [blame] | 52 | #if defined UCLINUX && !__THROW |
| 53 | /* workaround for libc bug */ |
| 54 | #define __THROW |
| 55 | #endif |
| 56 | |
Cyril Hrubis | 019ed6c | 2011-08-26 12:59:32 +0200 | [diff] [blame] | 57 | #define _GNU_SOURCE |
| 58 | |
nstraz | e321981 | 2003-07-14 17:06:37 +0000 | [diff] [blame] | 59 | #include <errno.h> |
nstraz | e321981 | 2003-07-14 17:06:37 +0000 | [diff] [blame] | 60 | #include <fcntl.h> |
| 61 | #include <sys/wait.h> |
mridge | fc9dd8c | 2004-05-11 21:37:01 +0000 | [diff] [blame] | 62 | #include <sys/types.h> |
| 63 | #include <sys/syscall.h> |
Cyril Hrubis | 019ed6c | 2011-08-26 12:59:32 +0200 | [diff] [blame] | 64 | #include <sched.h> |
nstraz | e321981 | 2003-07-14 17:06:37 +0000 | [diff] [blame] | 65 | #include "test.h" |
nstraz | e321981 | 2003-07-14 17:06:37 +0000 | [diff] [blame] | 66 | |
Wanlong Gao | 3dd0c6a | 2012-12-04 15:16:50 +0800 | [diff] [blame] | 67 | #define FLAG_ALL (CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|SIGCHLD) |
nstraz | e321981 | 2003-07-14 17:06:37 +0000 | [diff] [blame] | 68 | #define FLAG_NONE SIGCHLD |
| 69 | #define PARENT_VALUE 1 |
| 70 | #define CHILD_VALUE 2 |
| 71 | #define TRUE 1 |
| 72 | #define FALSE 0 |
| 73 | |
nstraz | 882ee2d | 2003-07-16 17:40:32 +0000 | [diff] [blame] | 74 | #include "clone_platform.h" |
nstraz | e321981 | 2003-07-14 17:06:37 +0000 | [diff] [blame] | 75 | |
Wanlong Gao | 3dd0c6a | 2012-12-04 15:16:50 +0800 | [diff] [blame] | 76 | static void setup(void); |
| 77 | static int test_setup(void); |
| 78 | static void cleanup(void); |
| 79 | static void test_cleanup(void); |
nstraz | e321981 | 2003-07-14 17:06:37 +0000 | [diff] [blame] | 80 | static int child_fn(); |
Wanlong Gao | 3dd0c6a | 2012-12-04 15:16:50 +0800 | [diff] [blame] | 81 | static int parent_test1(void); |
| 82 | static int parent_test2(void); |
| 83 | static int test_VM(void); |
| 84 | static int test_FS(void); |
| 85 | static int test_FILES(void); |
| 86 | static int test_SIG(void); |
| 87 | static int modified_VM(void); |
| 88 | static int modified_FS(void); |
| 89 | static int modified_FILES(void); |
| 90 | static int modified_SIG(void); |
| 91 | static void sig_child_defined_handler(int); |
nstraz | e321981 | 2003-07-14 17:06:37 +0000 | [diff] [blame] | 92 | static void sig_default_handler(); |
| 93 | |
nstraz | e321981 | 2003-07-14 17:06:37 +0000 | [diff] [blame] | 94 | static int fd_parent; |
| 95 | static char file_name[25]; |
| 96 | static int parent_variable; |
| 97 | static char cwd_parent[FILENAME_MAX]; |
| 98 | static int parent_got_signal, child_pid; |
| 99 | |
Wanlong Gao | 3dd0c6a | 2012-12-04 15:16:50 +0800 | [diff] [blame] | 100 | char *TCID = "clone02"; |
nstraz | e321981 | 2003-07-14 17:06:37 +0000 | [diff] [blame] | 101 | |
| 102 | struct test_case_t { |
| 103 | int flags; |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 104 | int (*parent_fn) (); |
nstraz | e321981 | 2003-07-14 17:06:37 +0000 | [diff] [blame] | 105 | } test_cases[] = { |
Wanlong Gao | 354ebb4 | 2012-12-07 10:10:04 +0800 | [diff] [blame] | 106 | { |
| 107 | FLAG_ALL, parent_test1}, { |
| 108 | FLAG_NONE, parent_test2} |
nstraz | e321981 | 2003-07-14 17:06:37 +0000 | [diff] [blame] | 109 | }; |
| 110 | |
| 111 | int TST_TOTAL = sizeof(test_cases) / sizeof(test_cases[0]); |
subrata_modak | bdbaec5 | 2009-02-26 12:14:51 +0000 | [diff] [blame] | 112 | |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 113 | int main(int ac, char **av) |
nstraz | e321981 | 2003-07-14 17:06:37 +0000 | [diff] [blame] | 114 | { |
| 115 | |
Cyril Hrubis | 89af32a | 2012-10-24 16:39:11 +0200 | [diff] [blame] | 116 | int lc; |
Cyril Hrubis | 0b9589f | 2014-05-27 17:40:33 +0200 | [diff] [blame] | 117 | const char *msg; |
Wanlong Gao | 3dd0c6a | 2012-12-04 15:16:50 +0800 | [diff] [blame] | 118 | void *child_stack; |
nstraz | e321981 | 2003-07-14 17:06:37 +0000 | [diff] [blame] | 119 | int status, i; |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 120 | |
Wanlong Gao | 3dd0c6a | 2012-12-04 15:16:50 +0800 | [diff] [blame] | 121 | msg = parse_opts(ac, av, NULL, NULL); |
| 122 | if (msg != NULL) |
Garrett Cooper | 60fa801 | 2010-11-22 13:50:58 -0800 | [diff] [blame] | 123 | tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg); |
nstraz | e321981 | 2003-07-14 17:06:37 +0000 | [diff] [blame] | 124 | |
nstraz | e321981 | 2003-07-14 17:06:37 +0000 | [diff] [blame] | 125 | setup(); |
| 126 | |
Wanlong Gao | 3dd0c6a | 2012-12-04 15:16:50 +0800 | [diff] [blame] | 127 | child_stack = malloc(CHILD_STACK_SIZE); |
| 128 | if (child_stack == NULL) |
nstraz | e321981 | 2003-07-14 17:06:37 +0000 | [diff] [blame] | 129 | tst_brkm(TBROK, cleanup, "Cannot allocate stack for child"); |
nstraz | e321981 | 2003-07-14 17:06:37 +0000 | [diff] [blame] | 130 | |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 131 | for (lc = 0; TEST_LOOPING(lc); lc++) { |
Caspar Zhang | d59a659 | 2013-03-07 14:59:12 +0800 | [diff] [blame] | 132 | tst_count = 0; |
nstraz | e321981 | 2003-07-14 17:06:37 +0000 | [diff] [blame] | 133 | |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 134 | for (i = 0; i < TST_TOTAL; ++i) { |
Garrett Cooper | 7e20b26 | 2010-12-17 02:23:12 -0800 | [diff] [blame] | 135 | if (test_setup() != 0) { |
nstraz | e321981 | 2003-07-14 17:06:37 +0000 | [diff] [blame] | 136 | tst_resm(TWARN, "test_setup() failed," |
| 137 | "skipping this test case"); |
| 138 | continue; |
| 139 | } |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 140 | |
nstraz | e321981 | 2003-07-14 17:06:37 +0000 | [diff] [blame] | 141 | /* Test the system call */ |
vapier | f6d7f09 | 2009-11-03 20:07:35 +0000 | [diff] [blame] | 142 | TEST(ltp_clone(test_cases[i].flags, child_fn, NULL, |
Wanlong Gao | 3dd0c6a | 2012-12-04 15:16:50 +0800 | [diff] [blame] | 143 | CHILD_STACK_SIZE, child_stack)); |
nstraz | e321981 | 2003-07-14 17:06:37 +0000 | [diff] [blame] | 144 | |
| 145 | /* check return code */ |
| 146 | if (TEST_RETURN == -1) { |
Wanlong Gao | 3dd0c6a | 2012-12-04 15:16:50 +0800 | [diff] [blame] | 147 | tst_resm(TFAIL | TTERRNO, "clone() failed"); |
nstraz | e321981 | 2003-07-14 17:06:37 +0000 | [diff] [blame] | 148 | /* Cleanup & continue with next test case */ |
| 149 | test_cleanup(); |
| 150 | continue; |
| 151 | } |
| 152 | |
| 153 | /* Wait for child to finish */ |
Garrett Cooper | 7e20b26 | 2010-12-17 02:23:12 -0800 | [diff] [blame] | 154 | if ((wait(&status)) == -1) { |
Wanlong Gao | 3dd0c6a | 2012-12-04 15:16:50 +0800 | [diff] [blame] | 155 | tst_resm(TWARN | TERRNO, |
| 156 | "wait failed; skipping testcase"); |
nstraz | e321981 | 2003-07-14 17:06:37 +0000 | [diff] [blame] | 157 | /* Cleanup & continue with next test case */ |
| 158 | test_cleanup(); |
| 159 | continue; |
| 160 | } |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 161 | |
Wanlong Gao | 3dd0c6a | 2012-12-04 15:16:50 +0800 | [diff] [blame] | 162 | if (WTERMSIG(status)) |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 163 | tst_resm(TWARN, "child exitied with signal %d", |
| 164 | WTERMSIG(status)); |
nstraz | e321981 | 2003-07-14 17:06:37 +0000 | [diff] [blame] | 165 | |
| 166 | /* |
Garrett Cooper | 7e20b26 | 2010-12-17 02:23:12 -0800 | [diff] [blame] | 167 | * Check the return value from child function and |
nstraz | e321981 | 2003-07-14 17:06:37 +0000 | [diff] [blame] | 168 | * parent function. If both functions returned |
| 169 | * successfully, test passed, else failed |
subrata_modak | bdbaec5 | 2009-02-26 12:14:51 +0000 | [diff] [blame] | 170 | */ |
Garrett Cooper | 7e20b26 | 2010-12-17 02:23:12 -0800 | [diff] [blame] | 171 | if (WIFEXITED(status) && WEXITSTATUS(status) == 0 && |
Wanlong Gao | 3dd0c6a | 2012-12-04 15:16:50 +0800 | [diff] [blame] | 172 | test_cases[i].parent_fn()) |
nstraz | e321981 | 2003-07-14 17:06:37 +0000 | [diff] [blame] | 173 | tst_resm(TPASS, "Test Passed"); |
Wanlong Gao | 3dd0c6a | 2012-12-04 15:16:50 +0800 | [diff] [blame] | 174 | else |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 175 | tst_resm(TFAIL, "Test Failed"); |
nstraz | e321981 | 2003-07-14 17:06:37 +0000 | [diff] [blame] | 176 | |
| 177 | /* Do test specific cleanup */ |
| 178 | test_cleanup(); |
| 179 | } |
Garrett Cooper | 2c28215 | 2010-12-16 00:55:50 -0800 | [diff] [blame] | 180 | } |
nstraz | e321981 | 2003-07-14 17:06:37 +0000 | [diff] [blame] | 181 | |
| 182 | free(child_stack); |
subrata_modak | bdbaec5 | 2009-02-26 12:14:51 +0000 | [diff] [blame] | 183 | |
nstraz | e321981 | 2003-07-14 17:06:37 +0000 | [diff] [blame] | 184 | cleanup(); |
Garrett Cooper | 5374050 | 2010-12-16 00:04:01 -0800 | [diff] [blame] | 185 | tst_exit(); |
Garrett Cooper | 2c28215 | 2010-12-16 00:55:50 -0800 | [diff] [blame] | 186 | } |
nstraz | e321981 | 2003-07-14 17:06:37 +0000 | [diff] [blame] | 187 | |
Wanlong Gao | 3dd0c6a | 2012-12-04 15:16:50 +0800 | [diff] [blame] | 188 | static void setup(void) |
nstraz | e321981 | 2003-07-14 17:06:37 +0000 | [diff] [blame] | 189 | { |
nstraz | e321981 | 2003-07-14 17:06:37 +0000 | [diff] [blame] | 190 | tst_sig(FORK, DEF_HANDLER, cleanup); |
nstraz | e321981 | 2003-07-14 17:06:37 +0000 | [diff] [blame] | 191 | TEST_PAUSE; |
nstraz | e321981 | 2003-07-14 17:06:37 +0000 | [diff] [blame] | 192 | tst_tmpdir(); |
subrata_modak | bdbaec5 | 2009-02-26 12:14:51 +0000 | [diff] [blame] | 193 | |
nstraz | e321981 | 2003-07-14 17:06:37 +0000 | [diff] [blame] | 194 | /* Get unique file name for each child process */ |
Garrett Cooper | 7e20b26 | 2010-12-17 02:23:12 -0800 | [diff] [blame] | 195 | if ((sprintf(file_name, "parent_file_%ld", syscall(__NR_gettid))) <= 0) |
Wanlong Gao | 3dd0c6a | 2012-12-04 15:16:50 +0800 | [diff] [blame] | 196 | tst_brkm(TBROK | TERRNO, cleanup, "sprintf() failed"); |
Garrett Cooper | 2c28215 | 2010-12-16 00:55:50 -0800 | [diff] [blame] | 197 | } |
nstraz | e321981 | 2003-07-14 17:06:37 +0000 | [diff] [blame] | 198 | |
Wanlong Gao | 3dd0c6a | 2012-12-04 15:16:50 +0800 | [diff] [blame] | 199 | static void cleanup(void) |
nstraz | e321981 | 2003-07-14 17:06:37 +0000 | [diff] [blame] | 200 | { |
Wanlong Gao | 3dd0c6a | 2012-12-04 15:16:50 +0800 | [diff] [blame] | 201 | if (unlink(file_name) == -1) |
| 202 | tst_resm(TWARN | TERRNO, "unlink(%s) failed", file_name); |
Garrett Cooper | 7e20b26 | 2010-12-17 02:23:12 -0800 | [diff] [blame] | 203 | tst_rmdir(); |
Garrett Cooper | 2c28215 | 2010-12-16 00:55:50 -0800 | [diff] [blame] | 204 | } |
nstraz | e321981 | 2003-07-14 17:06:37 +0000 | [diff] [blame] | 205 | |
Wanlong Gao | 3dd0c6a | 2012-12-04 15:16:50 +0800 | [diff] [blame] | 206 | static int test_setup(void) |
nstraz | e321981 | 2003-07-14 17:06:37 +0000 | [diff] [blame] | 207 | { |
| 208 | |
| 209 | struct sigaction def_act; |
| 210 | |
| 211 | /* Save current working directory of parent */ |
Garrett Cooper | 7e20b26 | 2010-12-17 02:23:12 -0800 | [diff] [blame] | 212 | if (getcwd(cwd_parent, sizeof(cwd_parent)) == NULL) { |
Wanlong Gao | 3dd0c6a | 2012-12-04 15:16:50 +0800 | [diff] [blame] | 213 | tst_resm(TWARN | TERRNO, "getcwd() failed in test_setup()"); |
Garrett Cooper | 7e20b26 | 2010-12-17 02:23:12 -0800 | [diff] [blame] | 214 | return -1; |
nstraz | e321981 | 2003-07-14 17:06:37 +0000 | [diff] [blame] | 215 | } |
| 216 | |
| 217 | /* |
| 218 | * Set value for parent_variable in parent, which will be |
| 219 | * changed by child in test_VM(), for testing CLONE_VM flag |
| 220 | */ |
| 221 | parent_variable = PARENT_VALUE; |
| 222 | |
| 223 | /* |
| 224 | * Open file from parent, which will be closed by |
| 225 | * child in test_FILES(), used for testing CLONE_FILES flag |
| 226 | */ |
Wanlong Gao | 3dd0c6a | 2012-12-04 15:16:50 +0800 | [diff] [blame] | 227 | fd_parent = open(file_name, O_CREAT | O_RDWR, 0777); |
| 228 | if (fd_parent == -1) { |
| 229 | tst_resm(TWARN | TERRNO, "open() failed in test_setup()"); |
Garrett Cooper | 7e20b26 | 2010-12-17 02:23:12 -0800 | [diff] [blame] | 230 | return -1; |
nstraz | e321981 | 2003-07-14 17:06:37 +0000 | [diff] [blame] | 231 | } |
| 232 | |
| 233 | /* |
| 234 | * set parent_got_signal to FALSE, used for testing |
| 235 | * CLONE_SIGHAND flag |
| 236 | */ |
| 237 | parent_got_signal = FALSE; |
| 238 | |
| 239 | /* Setup signal handler for SIGUSR2 */ |
| 240 | def_act.sa_handler = sig_default_handler; |
| 241 | def_act.sa_flags = SA_RESTART; |
Jan Stancek | cbec02d | 2013-04-02 12:16:58 +0200 | [diff] [blame] | 242 | sigemptyset(&def_act.sa_mask); |
nstraz | e321981 | 2003-07-14 17:06:37 +0000 | [diff] [blame] | 243 | |
Garrett Cooper | 7e20b26 | 2010-12-17 02:23:12 -0800 | [diff] [blame] | 244 | if (sigaction(SIGUSR2, &def_act, NULL) == -1) { |
Wanlong Gao | 3dd0c6a | 2012-12-04 15:16:50 +0800 | [diff] [blame] | 245 | tst_resm(TWARN | TERRNO, "sigaction() failed in test_setup()"); |
Garrett Cooper | 7e20b26 | 2010-12-17 02:23:12 -0800 | [diff] [blame] | 246 | return -1; |
nstraz | e321981 | 2003-07-14 17:06:37 +0000 | [diff] [blame] | 247 | } |
subrata_modak | bdbaec5 | 2009-02-26 12:14:51 +0000 | [diff] [blame] | 248 | |
Garrett Cooper | 7e20b26 | 2010-12-17 02:23:12 -0800 | [diff] [blame] | 249 | return 0; |
nstraz | e321981 | 2003-07-14 17:06:37 +0000 | [diff] [blame] | 250 | } |
| 251 | |
Wanlong Gao | 3dd0c6a | 2012-12-04 15:16:50 +0800 | [diff] [blame] | 252 | static void test_cleanup(void) |
nstraz | e321981 | 2003-07-14 17:06:37 +0000 | [diff] [blame] | 253 | { |
| 254 | |
| 255 | /* Restore parent's working directory */ |
Garrett Cooper | 7e20b26 | 2010-12-17 02:23:12 -0800 | [diff] [blame] | 256 | if (chdir(cwd_parent) == -1) { |
Garrett Cooper | 1e6f5a6 | 2010-12-19 09:58:10 -0800 | [diff] [blame] | 257 | /* |
Garrett Cooper | 7e20b26 | 2010-12-17 02:23:12 -0800 | [diff] [blame] | 258 | * we have to exit here |
| 259 | * |
| 260 | * XXX (garrcoop): why??? |
| 261 | */ |
Wanlong Gao | 3dd0c6a | 2012-12-04 15:16:50 +0800 | [diff] [blame] | 262 | tst_brkm(TBROK | TERRNO, cleanup, |
| 263 | "chdir() failed in test_cleanup()"); |
nstraz | e321981 | 2003-07-14 17:06:37 +0000 | [diff] [blame] | 264 | } |
| 265 | |
| 266 | } |
| 267 | |
Mike Frysinger | c57fba5 | 2014-04-09 18:56:30 -0400 | [diff] [blame] | 268 | static int child_fn(void) |
nstraz | e321981 | 2003-07-14 17:06:37 +0000 | [diff] [blame] | 269 | { |
| 270 | |
| 271 | /* save child pid */ |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 272 | child_pid = syscall(__NR_gettid); |
mridge | fc9dd8c | 2004-05-11 21:37:01 +0000 | [diff] [blame] | 273 | |
Garrett Cooper | 7e20b26 | 2010-12-17 02:23:12 -0800 | [diff] [blame] | 274 | if (test_VM() == 0 && test_FILES() == 0 && test_FS() == 0 && |
| 275 | test_SIG() == 0) |
| 276 | exit(0); |
| 277 | exit(1); |
nstraz | e321981 | 2003-07-14 17:06:37 +0000 | [diff] [blame] | 278 | } |
| 279 | |
Wanlong Gao | 3dd0c6a | 2012-12-04 15:16:50 +0800 | [diff] [blame] | 280 | static int parent_test1(void) |
nstraz | e321981 | 2003-07-14 17:06:37 +0000 | [diff] [blame] | 281 | { |
subrata_modak | bdbaec5 | 2009-02-26 12:14:51 +0000 | [diff] [blame] | 282 | |
nstraz | e321981 | 2003-07-14 17:06:37 +0000 | [diff] [blame] | 283 | /* |
| 284 | * For first test case (with all flags set), all resources are |
| 285 | * shared between parent and child. So whatever changes made by |
| 286 | * child should get reflected in parent also. modified_*() |
| 287 | * functions check this. All of them should return 1 for |
| 288 | * parent_test1() to return 1 |
| 289 | */ |
subrata_modak | bdbaec5 | 2009-02-26 12:14:51 +0000 | [diff] [blame] | 290 | |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 291 | if (modified_VM() && modified_FILES() && modified_FS() && |
Garrett Cooper | 7e20b26 | 2010-12-17 02:23:12 -0800 | [diff] [blame] | 292 | modified_SIG()) |
| 293 | return 0; |
| 294 | return -1; |
nstraz | e321981 | 2003-07-14 17:06:37 +0000 | [diff] [blame] | 295 | } |
| 296 | |
Wanlong Gao | 3dd0c6a | 2012-12-04 15:16:50 +0800 | [diff] [blame] | 297 | static int parent_test2(void) |
nstraz | e321981 | 2003-07-14 17:06:37 +0000 | [diff] [blame] | 298 | { |
| 299 | |
| 300 | /* |
| 301 | * For second test case (with no resouce shared), all of the |
| 302 | * modified_*() functions should return 0 for parent_test2() |
| 303 | * to return 1 |
| 304 | */ |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 305 | if (modified_VM() || modified_FILES() || modified_FS() || |
Wanlong Gao | 3dd0c6a | 2012-12-04 15:16:50 +0800 | [diff] [blame] | 306 | modified_SIG()) |
nstraz | e321981 | 2003-07-14 17:06:37 +0000 | [diff] [blame] | 307 | return 0; |
Wanlong Gao | 3dd0c6a | 2012-12-04 15:16:50 +0800 | [diff] [blame] | 308 | |
Garrett Cooper | 7e20b26 | 2010-12-17 02:23:12 -0800 | [diff] [blame] | 309 | return -1; |
nstraz | e321981 | 2003-07-14 17:06:37 +0000 | [diff] [blame] | 310 | } |
| 311 | |
| 312 | /* |
| 313 | * test_VM() - function to change parent_variable from child's |
| 314 | * address space. If CLONE_VM flag is set, child shares |
| 315 | * the memory space with parent so this will be visible |
| 316 | * to parent also. |
| 317 | */ |
| 318 | |
Wanlong Gao | 3dd0c6a | 2012-12-04 15:16:50 +0800 | [diff] [blame] | 319 | static int test_VM(void) |
nstraz | e321981 | 2003-07-14 17:06:37 +0000 | [diff] [blame] | 320 | { |
| 321 | parent_variable = CHILD_VALUE; |
Garrett Cooper | 7e20b26 | 2010-12-17 02:23:12 -0800 | [diff] [blame] | 322 | return 0; |
nstraz | e321981 | 2003-07-14 17:06:37 +0000 | [diff] [blame] | 323 | } |
| 324 | |
| 325 | /* |
| 326 | * test_FILES() - This function closes a file descriptor opened by |
| 327 | * parent. If CLONE_FILES flag is set, the parent and |
| 328 | * the child process share the same file descriptor |
| 329 | * table. so this affects the parent also |
| 330 | */ |
Wanlong Gao | 3dd0c6a | 2012-12-04 15:16:50 +0800 | [diff] [blame] | 331 | static int test_FILES(void) |
nstraz | e321981 | 2003-07-14 17:06:37 +0000 | [diff] [blame] | 332 | { |
Garrett Cooper | 7e20b26 | 2010-12-17 02:23:12 -0800 | [diff] [blame] | 333 | if (close(fd_parent) == -1) { |
Wanlong Gao | 3dd0c6a | 2012-12-04 15:16:50 +0800 | [diff] [blame] | 334 | tst_resm(TWARN | TERRNO, "close failed in test_FILES"); |
Garrett Cooper | 7e20b26 | 2010-12-17 02:23:12 -0800 | [diff] [blame] | 335 | return -1; |
nstraz | e321981 | 2003-07-14 17:06:37 +0000 | [diff] [blame] | 336 | } |
Garrett Cooper | 7e20b26 | 2010-12-17 02:23:12 -0800 | [diff] [blame] | 337 | return 0; |
nstraz | e321981 | 2003-07-14 17:06:37 +0000 | [diff] [blame] | 338 | } |
| 339 | |
| 340 | /* |
| 341 | * test_FS() - This function changes the current working directory |
| 342 | * of the child process. If CLONE_FS flag is set, this |
| 343 | * will be visible to parent also. |
| 344 | */ |
Wanlong Gao | 3dd0c6a | 2012-12-04 15:16:50 +0800 | [diff] [blame] | 345 | static int test_FS(void) |
nstraz | e321981 | 2003-07-14 17:06:37 +0000 | [diff] [blame] | 346 | { |
Garrett Cooper | 7e20b26 | 2010-12-17 02:23:12 -0800 | [diff] [blame] | 347 | char *test_tmpdir; |
| 348 | int rval; |
| 349 | |
Cyril Hrubis | 9c31ad2 | 2014-05-14 17:15:39 +0200 | [diff] [blame] | 350 | test_tmpdir = tst_get_tmpdir(); |
Garrett Cooper | 7e20b26 | 2010-12-17 02:23:12 -0800 | [diff] [blame] | 351 | if (test_tmpdir == NULL) { |
Cyril Hrubis | 9c31ad2 | 2014-05-14 17:15:39 +0200 | [diff] [blame] | 352 | tst_resm(TWARN | TERRNO, "tst_get_tmpdir failed"); |
Garrett Cooper | 7e20b26 | 2010-12-17 02:23:12 -0800 | [diff] [blame] | 353 | rval = -1; |
| 354 | } else if (chdir(test_tmpdir) == -1) { |
Wanlong Gao | 3dd0c6a | 2012-12-04 15:16:50 +0800 | [diff] [blame] | 355 | tst_resm(TWARN | TERRNO, "chdir failed in test_FS"); |
Garrett Cooper | 7e20b26 | 2010-12-17 02:23:12 -0800 | [diff] [blame] | 356 | rval = -1; |
Wanlong Gao | 3dd0c6a | 2012-12-04 15:16:50 +0800 | [diff] [blame] | 357 | } else { |
Garrett Cooper | 7e20b26 | 2010-12-17 02:23:12 -0800 | [diff] [blame] | 358 | rval = 0; |
Wanlong Gao | 3dd0c6a | 2012-12-04 15:16:50 +0800 | [diff] [blame] | 359 | } |
| 360 | |
Garrett Cooper | 7e20b26 | 2010-12-17 02:23:12 -0800 | [diff] [blame] | 361 | free(test_tmpdir); |
| 362 | return rval; |
nstraz | e321981 | 2003-07-14 17:06:37 +0000 | [diff] [blame] | 363 | } |
| 364 | |
| 365 | /* |
| 366 | * test_SIG() - This function changes the signal handler for SIGUSR2 |
| 367 | * signal for child. If CLONE_SIGHAND flag is set, this |
| 368 | * affects parent also. |
| 369 | */ |
Wanlong Gao | 3dd0c6a | 2012-12-04 15:16:50 +0800 | [diff] [blame] | 370 | static int test_SIG(void) |
nstraz | e321981 | 2003-07-14 17:06:37 +0000 | [diff] [blame] | 371 | { |
| 372 | |
| 373 | struct sigaction new_act; |
subrata_modak | bdbaec5 | 2009-02-26 12:14:51 +0000 | [diff] [blame] | 374 | |
nstraz | e321981 | 2003-07-14 17:06:37 +0000 | [diff] [blame] | 375 | new_act.sa_handler = sig_child_defined_handler; |
| 376 | new_act.sa_flags = SA_RESTART; |
Jan Stancek | cbec02d | 2013-04-02 12:16:58 +0200 | [diff] [blame] | 377 | sigemptyset(&new_act.sa_mask); |
subrata_modak | bdbaec5 | 2009-02-26 12:14:51 +0000 | [diff] [blame] | 378 | |
nstraz | e321981 | 2003-07-14 17:06:37 +0000 | [diff] [blame] | 379 | /* Set signal handler to sig_child_defined_handler */ |
Garrett Cooper | 7e20b26 | 2010-12-17 02:23:12 -0800 | [diff] [blame] | 380 | if (sigaction(SIGUSR2, &new_act, NULL) == -1) { |
Wanlong Gao | 3dd0c6a | 2012-12-04 15:16:50 +0800 | [diff] [blame] | 381 | tst_resm(TWARN | TERRNO, "signal failed in test_SIG"); |
Garrett Cooper | 7e20b26 | 2010-12-17 02:23:12 -0800 | [diff] [blame] | 382 | return -1; |
nstraz | e321981 | 2003-07-14 17:06:37 +0000 | [diff] [blame] | 383 | } |
| 384 | |
| 385 | /* Send SIGUSR2 signal to parent */ |
Garrett Cooper | 7e20b26 | 2010-12-17 02:23:12 -0800 | [diff] [blame] | 386 | if (kill(getppid(), SIGUSR2) == -1) { |
Wanlong Gao | 3dd0c6a | 2012-12-04 15:16:50 +0800 | [diff] [blame] | 387 | tst_resm(TWARN | TERRNO, "kill failed in test_SIG"); |
Garrett Cooper | 7e20b26 | 2010-12-17 02:23:12 -0800 | [diff] [blame] | 388 | return -1; |
nstraz | e321981 | 2003-07-14 17:06:37 +0000 | [diff] [blame] | 389 | } |
Wanlong Gao | 3dd0c6a | 2012-12-04 15:16:50 +0800 | [diff] [blame] | 390 | |
Garrett Cooper | 7e20b26 | 2010-12-17 02:23:12 -0800 | [diff] [blame] | 391 | return 0; |
nstraz | e321981 | 2003-07-14 17:06:37 +0000 | [diff] [blame] | 392 | } |
| 393 | |
| 394 | /* |
| 395 | * modified_VM() - This function is called by parent process to check |
| 396 | * whether child's modification to parent_variable |
| 397 | * is visible to parent |
| 398 | */ |
| 399 | |
Wanlong Gao | 3dd0c6a | 2012-12-04 15:16:50 +0800 | [diff] [blame] | 400 | static int modified_VM(void) |
nstraz | e321981 | 2003-07-14 17:06:37 +0000 | [diff] [blame] | 401 | { |
| 402 | |
Wanlong Gao | 3dd0c6a | 2012-12-04 15:16:50 +0800 | [diff] [blame] | 403 | if (parent_variable == CHILD_VALUE) |
nstraz | e321981 | 2003-07-14 17:06:37 +0000 | [diff] [blame] | 404 | /* child has modified parent_variable */ |
| 405 | return 1; |
Wanlong Gao | 3dd0c6a | 2012-12-04 15:16:50 +0800 | [diff] [blame] | 406 | |
nstraz | e321981 | 2003-07-14 17:06:37 +0000 | [diff] [blame] | 407 | return 0; |
| 408 | } |
| 409 | |
| 410 | /* |
| 411 | * modified_FILES() - This function checks for file descriptor table |
| 412 | * modifications done by child |
| 413 | */ |
Wanlong Gao | 3dd0c6a | 2012-12-04 15:16:50 +0800 | [diff] [blame] | 414 | static int modified_FILES(void) |
nstraz | e321981 | 2003-07-14 17:06:37 +0000 | [diff] [blame] | 415 | { |
| 416 | char buff[20]; |
subrata_modak | bdbaec5 | 2009-02-26 12:14:51 +0000 | [diff] [blame] | 417 | |
Wanlong Gao | 3dd0c6a | 2012-12-04 15:16:50 +0800 | [diff] [blame] | 418 | if (((read(fd_parent, buff, sizeof(buff))) == -1) && (errno == EBADF)) |
nstraz | e321981 | 2003-07-14 17:06:37 +0000 | [diff] [blame] | 419 | /* Child has closed this file descriptor */ |
| 420 | return 1; |
nstraz | e321981 | 2003-07-14 17:06:37 +0000 | [diff] [blame] | 421 | |
subrata_modak | 56207ce | 2009-03-23 13:35:39 +0000 | [diff] [blame] | 422 | /* close fd_parent */ |
Wanlong Gao | 3dd0c6a | 2012-12-04 15:16:50 +0800 | [diff] [blame] | 423 | if ((close(fd_parent)) == -1) |
| 424 | tst_resm(TWARN | TERRNO, "close() failed in modified_FILES()"); |
subrata_modak | bdbaec5 | 2009-02-26 12:14:51 +0000 | [diff] [blame] | 425 | |
nstraz | e321981 | 2003-07-14 17:06:37 +0000 | [diff] [blame] | 426 | return 0; |
| 427 | } |
| 428 | |
| 429 | /* |
| 430 | * modified_FS() - This function checks parent's current working directory |
| 431 | * to see whether its modified by child or not. |
| 432 | */ |
Wanlong Gao | 3dd0c6a | 2012-12-04 15:16:50 +0800 | [diff] [blame] | 433 | static int modified_FS(void) |
nstraz | e321981 | 2003-07-14 17:06:37 +0000 | [diff] [blame] | 434 | { |
| 435 | char cwd[FILENAME_MAX]; |
subrata_modak | bdbaec5 | 2009-02-26 12:14:51 +0000 | [diff] [blame] | 436 | |
Wanlong Gao | 3dd0c6a | 2012-12-04 15:16:50 +0800 | [diff] [blame] | 437 | if ((getcwd(cwd, sizeof(cwd))) == NULL) |
| 438 | tst_resm(TWARN | TERRNO, "getcwd() failed"); |
subrata_modak | bdbaec5 | 2009-02-26 12:14:51 +0000 | [diff] [blame] | 439 | |
Wanlong Gao | 3dd0c6a | 2012-12-04 15:16:50 +0800 | [diff] [blame] | 440 | if (!(strcmp(cwd, cwd_parent))) |
nstraz | e321981 | 2003-07-14 17:06:37 +0000 | [diff] [blame] | 441 | /* cwd hasn't changed */ |
| 442 | return 0; |
Wanlong Gao | 3dd0c6a | 2012-12-04 15:16:50 +0800 | [diff] [blame] | 443 | |
nstraz | e321981 | 2003-07-14 17:06:37 +0000 | [diff] [blame] | 444 | return 1; |
| 445 | } |
| 446 | |
| 447 | /* |
| 448 | * modified_SIG() - This function checks whether child has changed |
| 449 | * parent's signal handler for signal, SIGUSR2 |
| 450 | */ |
Wanlong Gao | 3dd0c6a | 2012-12-04 15:16:50 +0800 | [diff] [blame] | 451 | static int modified_SIG(void) |
nstraz | e321981 | 2003-07-14 17:06:37 +0000 | [diff] [blame] | 452 | { |
subrata_modak | bdbaec5 | 2009-02-26 12:14:51 +0000 | [diff] [blame] | 453 | |
Wanlong Gao | 3dd0c6a | 2012-12-04 15:16:50 +0800 | [diff] [blame] | 454 | if (parent_got_signal) |
nstraz | e321981 | 2003-07-14 17:06:37 +0000 | [diff] [blame] | 455 | /* |
| 456 | * parent came through sig_child_defined_handler() |
| 457 | * this means child has changed parent's handler |
| 458 | */ |
| 459 | return 1; |
Wanlong Gao | 3dd0c6a | 2012-12-04 15:16:50 +0800 | [diff] [blame] | 460 | |
nstraz | e321981 | 2003-07-14 17:06:37 +0000 | [diff] [blame] | 461 | return 0; |
| 462 | } |
| 463 | |
| 464 | /* |
| 465 | * sig_child_defined_handler() - Signal handler installed by child |
| 466 | */ |
Wanlong Gao | 3dd0c6a | 2012-12-04 15:16:50 +0800 | [diff] [blame] | 467 | static void sig_child_defined_handler(int pid) |
nstraz | e321981 | 2003-07-14 17:06:37 +0000 | [diff] [blame] | 468 | { |
Wanlong Gao | 3dd0c6a | 2012-12-04 15:16:50 +0800 | [diff] [blame] | 469 | if ((syscall(__NR_gettid)) == child_pid) |
nstraz | e321981 | 2003-07-14 17:06:37 +0000 | [diff] [blame] | 470 | /* Child got signal, give warning */ |
| 471 | tst_resm(TWARN, "Child got SIGUSR2 signal"); |
Wanlong Gao | 3dd0c6a | 2012-12-04 15:16:50 +0800 | [diff] [blame] | 472 | else |
nstraz | e321981 | 2003-07-14 17:06:37 +0000 | [diff] [blame] | 473 | parent_got_signal = TRUE; |
nstraz | e321981 | 2003-07-14 17:06:37 +0000 | [diff] [blame] | 474 | } |
| 475 | |
| 476 | /* sig_default_handler() - Default handler for parent */ |
Mike Frysinger | c57fba5 | 2014-04-09 18:56:30 -0400 | [diff] [blame] | 477 | static void sig_default_handler(void) |
nstraz | e321981 | 2003-07-14 17:06:37 +0000 | [diff] [blame] | 478 | { |
Cyril Hrubis | 019ed6c | 2011-08-26 12:59:32 +0200 | [diff] [blame] | 479 | } |