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 "mountns_helper.h" 44 #include "test.h" 45 #include "safe_macros.h" 46 47 char *TCID = "mountns02"; 48 int TST_TOTAL = 2; 49 50 #if defined(MS_SHARED) && defined(MS_PRIVATE) && defined(MS_REC) 51 52 int child_func(void *arg LTP_ATTRIBUTE_UNUSED) 53 { 54 int ret = 0; 55 56 TST_SAFE_CHECKPOINT_WAIT(NULL, 0); 57 58 if ((access(DIRA"/A", F_OK) != 0) || (access(DIRA"/B", F_OK) == 0)) 59 ret = 2; 60 61 TST_SAFE_CHECKPOINT_WAKE_AND_WAIT(NULL, 0); 62 63 /* bind mounts DIRB to DIRA making contents of DIRB visible 64 * in DIRA */ 65 if (mount(DIRB, DIRA, "none", MS_BIND, NULL) == -1) { 66 perror("mount"); 67 return 1; 68 } 69 70 TST_SAFE_CHECKPOINT_WAKE_AND_WAIT(NULL, 0); 71 72 umount(DIRA); 73 return ret; 74 } 75 76 static void test(void) 77 { 78 int status; 79 80 /* unshares the mount ns */ 81 if (unshare(CLONE_NEWNS) == -1) 82 tst_brkm(TBROK | TERRNO, cleanup, "unshare failed"); 83 /* makes sure parent mounts/umounts have no effect on a real system */ 84 SAFE_MOUNT(cleanup, "none", "/", "none", MS_REC|MS_PRIVATE, NULL); 85 86 /* bind mounts DIRA to itself */ 87 SAFE_MOUNT(cleanup, DIRA, DIRA, "none", MS_BIND, NULL); 88 89 /* makes mount DIRA private */ 90 SAFE_MOUNT(cleanup, "none", DIRA, "none", MS_PRIVATE, NULL); 91 92 if (do_clone_tests(CLONE_NEWNS, child_func, NULL, NULL, NULL) == -1) 93 tst_brkm(TBROK | TERRNO, cleanup, "clone failed"); 94 95 /* bind mounts DIRB to DIRA making contents of DIRB visible 96 * in DIRA */ 97 SAFE_MOUNT(cleanup, DIRB, DIRA, "none", MS_BIND, NULL); 98 99 TST_SAFE_CHECKPOINT_WAKE_AND_WAIT(cleanup, 0); 100 101 SAFE_UMOUNT(cleanup, DIRA); 102 103 TST_SAFE_CHECKPOINT_WAKE_AND_WAIT(cleanup, 0); 104 105 if ((access(DIRA"/A", F_OK) != 0) || (access(DIRA"/B", F_OK) == 0)) 106 tst_resm(TFAIL, "private mount in child failed"); 107 else 108 tst_resm(TPASS, "private mount in child passed"); 109 110 TST_SAFE_CHECKPOINT_WAKE(cleanup, 0); 111 112 113 SAFE_WAIT(cleanup, &status); 114 if (WIFEXITED(status)) { 115 if ((WEXITSTATUS(status) == 0)) 116 tst_resm(TPASS, "private mount in parent passed"); 117 else 118 tst_resm(TFAIL, "private mount in parent failed"); 119 } 120 if (WIFSIGNALED(status)) { 121 tst_resm(TBROK, "child was killed with signal %s", 122 tst_strsig(WTERMSIG(status))); 123 return; 124 } 125 126 SAFE_UMOUNT(cleanup, DIRA); 127 } 128 129 int main(int argc, char *argv[]) 130 { 131 int lc; 132 133 tst_parse_opts(argc, argv, NULL, NULL); 134 135 setup(); 136 137 for (lc = 0; TEST_LOOPING(lc); lc++) 138 test(); 139 140 cleanup(); 141 tst_exit(); 142 } 143 144 #else 145 int main(void) 146 { 147 tst_brkm(TCONF, NULL, "needed mountflags are not defined"); 148 } 149 #endif 150