1 /* 2 * Copyright (c) International Business Machines Corp., 2009 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 * 8 * This program is distributed in the hope that it will be useful, 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 11 * the GNU General Public License for more details. 12 * You should have received a copy of the GNU General Public License 13 * along with this program; if not, write to the Free Software 14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 15 * 16 * Author: Serge Hallyn <serue (at) us.ibm.com> 17 * 18 * Check mqueuefs lifetime 19 * . parent creates /dev/mqueue2 20 * . child mounts mqueue there 21 * . child does mq_open("/ab") 22 * . parent checks for /dev/mqueue2 23 * . child exits 24 * . parent checks for /dev/mqueue2 25 * . parent tries 'touch /dev/mqueue2/dd' -> should fail 26 * . parent umounts /dev/mqueue2 27 28 ***************************************************************************/ 29 30 #ifndef _GNU_SOURCE 31 #define _GNU_SOURCE 32 #endif 33 #include <sys/types.h> 34 #include <sys/stat.h> 35 #include <sys/wait.h> 36 #include <assert.h> 37 #include <stdio.h> 38 #include <stdlib.h> 39 #include <unistd.h> 40 #include <string.h> 41 #include <errno.h> 42 #include "mqns.h" 43 #include "mqns_helper.h" 44 45 char *TCID = "posixmq_namespace_04"; 46 int TST_TOTAL = 1; 47 48 int p1[2]; 49 int p2[2]; 50 51 #define FNAM1 DEV_MQUEUE2 SLASH_MQ1 52 #define FNAM2 DEV_MQUEUE2 SLASH_MQ2 53 54 int check_mqueue(void *vtest) 55 { 56 char buf[30]; 57 mqd_t mqd; 58 int rc; 59 60 (void) vtest; 61 62 close(p1[1]); 63 close(p2[0]); 64 65 read(p1[0], buf, 3); /* go */ 66 67 mqd = ltp_syscall(__NR_mq_open, NOSLASH_MQ1, O_RDWR | O_CREAT | O_EXCL, 68 0755, NULL); 69 if (mqd == -1) { 70 write(p2[1], "mqfail", 7); 71 tst_exit(); 72 } 73 74 mq_close(mqd); 75 76 rc = mount("mqueue", DEV_MQUEUE2, "mqueue", 0, NULL); 77 if (rc == -1) { 78 perror("mount"); 79 write(p2[1], "mount", 6); 80 tst_exit(); 81 } 82 83 write(p2[1], "go", 3); 84 read(p1[0], buf, 3); 85 86 tst_exit(); 87 } 88 89 static void setup(void) 90 { 91 tst_require_root(); 92 check_mqns(); 93 } 94 95 int main(int argc, char *argv[]) 96 { 97 int rc; 98 int status; 99 char buf[30]; 100 struct stat statbuf; 101 int use_clone = T_UNSHARE; 102 103 setup(); 104 105 if (argc == 2 && strcmp(argv[1], "-clone") == 0) { 106 tst_resm(TINFO, 107 "Testing posix mq namespaces through clone(2)."); 108 use_clone = T_CLONE; 109 } else 110 tst_resm(TINFO, 111 "Testing posix mq namespaces through unshare(2)."); 112 113 if (pipe(p1) == -1) { 114 perror("pipe"); 115 exit(EXIT_FAILURE); 116 } 117 if (pipe(p2) == -1) { 118 perror("pipe"); 119 exit(EXIT_FAILURE); 120 } 121 122 mkdir(DEV_MQUEUE2, 0755); 123 124 tst_resm(TINFO, "Checking mqueue filesystem lifetime"); 125 126 /* fire off the test */ 127 rc = do_clone_unshare_test(use_clone, CLONE_NEWIPC, check_mqueue, NULL); 128 if (rc < 0) { 129 tst_resm(TFAIL, "failed clone/unshare"); 130 goto fail; 131 } 132 133 close(p1[0]); 134 close(p2[1]); 135 write(p1[1], "go", 3); 136 137 read(p2[0], buf, 7); 138 if (!strcmp(buf, "mqfail")) { 139 tst_resm(TFAIL, "child process could not create mqueue"); 140 goto fail; 141 } else if (!strcmp(buf, "mount")) { 142 tst_resm(TFAIL, "child process could not mount mqueue"); 143 goto fail; 144 } 145 146 rc = stat(FNAM1, &statbuf); 147 if (rc == -1) { 148 perror("stat"); 149 write(p1[1], "go", 3); 150 tst_resm(TFAIL, "parent could not see child's created mq"); 151 goto fail; 152 } 153 write(p1[1], "go", 3); 154 155 rc = wait(&status); 156 if (rc == -1) { 157 perror("wait"); 158 tst_resm(TFAIL, "error while parent waited on child to exit"); 159 goto fail; 160 } 161 if (!WIFEXITED(status)) { 162 tst_resm(TFAIL, "Child did not exit normally (status %d)", 163 status); 164 goto fail; 165 } 166 rc = stat(FNAM1, &statbuf); 167 if (rc == -1) { 168 tst_resm(TFAIL, 169 "parent's view of child's mq died with child"); 170 goto fail; 171 } 172 173 rc = creat(FNAM2, 0755); 174 if (rc != -1) { 175 tst_resm(TFAIL, 176 "parent was able to create a file in dead child's mqfs"); 177 goto fail; 178 } 179 180 tst_resm(TPASS, "Child mqueue fs still visible for parent"); 181 182 fail: 183 umount(DEV_MQUEUE2); 184 rmdir(DEV_MQUEUE2); 185 186 tst_exit(); 187 } 188