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@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 45char *TCID = "posixmq_namespace_04"; 46int TST_TOTAL = 1; 47 48int p1[2]; 49int p2[2]; 50 51#define FNAM1 DEV_MQUEUE2 SLASH_MQ1 52#define FNAM2 DEV_MQUEUE2 SLASH_MQ2 53 54int 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 89static void setup(void) 90{ 91 tst_require_root(); 92 check_mqns(); 93} 94 95int 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 182fail: 183 umount(DEV_MQUEUE2); 184 rmdir(DEV_MQUEUE2); 185 186 tst_exit(); 187} 188