1 /* Copyright (c) 2014 Red Hat, Inc. 2 * 3 * This program is free software: you can redistribute it and/or modify 4 * it under the terms of version 2 the GNU General Public License as 5 * published by the Free Software Foundation. 6 * 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 the 10 * GNU General Public License for more details. 11 * 12 * You should have received a copy of the GNU General Public License 13 * along with this program. If not, see <http://www.gnu.org/licenses/>. 14 *********************************************************************** 15 * File: mountns02.c 16 * 17 * Tests a private mount: private mount does not forward or receive 18 * propagation. 19 * Description: 20 * 1. Creates directories "A", "B" and files "A/A", "B/B" 21 * 2. Unshares mount namespace and makes it private (so mounts/umounts 22 * have no effect on a real system) 23 * 3. Bind mounts directory "A" to "A" 24 * 4. Makes directory "A" private 25 * 5. Clones a new child process with CLONE_NEWNS flag 26 * 6. There are two test cases (where X is parent namespace and Y child 27 * namespace): 28 * 1) 29 * X: bind mounts "B" to "A" 30 * Y: must see "A/A" and must not see "A/B" 31 * X: umounts "A" 32 * 2) 33 * Y: bind mounts "B" to "A" 34 * X: must see "A/A" and must not see "A/B" 35 * Y: umounts A 36 ***********************************************************************/ 37 38 #define _GNU_SOURCE 39 #include <sys/wait.h> 40 #include <sys/mount.h> 41 #include <stdio.h> 42 #include <errno.h> 43 #include "test.h" 44 #include "libclone.h" 45 #include "safe_macros.h" 46 #include "mountns_helper.h" 47 48 49 char *TCID = "mountns02"; 50 int TST_TOTAL = 2; 51 52 53 #if defined(MS_SHARED) && defined(MS_PRIVATE) && defined(MS_REC) 54 55 int child_func(void *arg LTP_ATTRIBUTE_UNUSED) 56 { 57 int ret = 0; 58 59 TST_SAFE_CHECKPOINT_WAIT(NULL, 0); 60 61 if ((access(DIRA"/A", F_OK) != 0) || (access(DIRA"/B", F_OK) == 0)) 62 ret = 2; 63 64 TST_SAFE_CHECKPOINT_WAKE_AND_WAIT(NULL, 0); 65 66 /* bind mounts DIRB to DIRA making contents of DIRB visible 67 * in DIRA */ 68 if (mount(DIRB, DIRA, "none", MS_BIND, NULL) == -1) { 69 perror("mount"); 70 return 1; 71 } 72 73 TST_SAFE_CHECKPOINT_WAKE_AND_WAIT(NULL, 0); 74 75 umount(DIRA); 76 return ret; 77 } 78 79 static void test(void) 80 { 81 int status; 82 83 /* unshares the mount ns */ 84 if (unshare(CLONE_NEWNS) == -1) 85 tst_brkm(TBROK | TERRNO, cleanup, "unshare failed"); 86 /* makes sure parent mounts/umounts have no effect on a real system */ 87 SAFE_MOUNT(cleanup, "none", "/", "none", MS_REC|MS_PRIVATE, NULL); 88 89 /* bind mounts DIRA to itself */ 90 SAFE_MOUNT(cleanup, DIRA, DIRA, "none", MS_BIND, NULL); 91 92 /* makes mount DIRA private */ 93 SAFE_MOUNT(cleanup, "none", DIRA, "none", MS_PRIVATE, NULL); 94 95 if (do_clone_tests(CLONE_NEWNS, child_func, NULL, NULL, NULL) == -1) 96 tst_brkm(TBROK | TERRNO, cleanup, "clone failed"); 97 98 /* bind mounts DIRB to DIRA making contents of DIRB visible 99 * in DIRA */ 100 SAFE_MOUNT(cleanup, DIRB, DIRA, "none", MS_BIND, NULL); 101 102 TST_SAFE_CHECKPOINT_WAKE_AND_WAIT(cleanup, 0); 103 104 SAFE_UMOUNT(cleanup, DIRA); 105 106 TST_SAFE_CHECKPOINT_WAKE_AND_WAIT(cleanup, 0); 107 108 if ((access(DIRA"/A", F_OK) != 0) || (access(DIRA"/B", F_OK) == 0)) 109 tst_resm(TFAIL, "private mount in child failed"); 110 else 111 tst_resm(TPASS, "private mount in child passed"); 112 113 TST_SAFE_CHECKPOINT_WAKE(cleanup, 0); 114 115 116 SAFE_WAIT(cleanup, &status); 117 if (WIFEXITED(status)) { 118 if ((WEXITSTATUS(status) == 0)) 119 tst_resm(TPASS, "private mount in parent passed"); 120 else 121 tst_resm(TFAIL, "private mount in parent failed"); 122 } 123 if (WIFSIGNALED(status)) { 124 tst_resm(TBROK, "child was killed with signal %s", 125 tst_strsig(WTERMSIG(status))); 126 return; 127 } 128 129 SAFE_UMOUNT(cleanup, DIRA); 130 } 131 132 int main(int argc, char *argv[]) 133 { 134 int lc; 135 136 tst_parse_opts(argc, argv, NULL, NULL); 137 138 setup(); 139 140 for (lc = 0; TEST_LOOPING(lc); lc++) 141 test(); 142 143 cleanup(); 144 tst_exit(); 145 } 146 147 #else 148 int main(void) 149 { 150 tst_brkm(TCONF, NULL, "needed mountflags are not defined"); 151 } 152 #endif 153