Home | History | Annotate | Download | only in mqns
      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