Home | History | Annotate | Download | only in mqns
      1 /*
      2 * Copyright (c) International Business Machines Corp., 2009
      3 * Copyright (c) Nadia Derbey, 2009
      4 * This program is free software; you can redistribute it and/or modify
      5 * it under the terms of the GNU General Public License as published by
      6 * the Free Software Foundation; either version 2 of the License, or
      7 * (at your option) any later version.
      8 *
      9 * This program is distributed in the hope that it will be useful,
     10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
     12 * the GNU General Public License for more details.
     13 * You should have received a copy of the GNU General Public License
     14 * along with this program; if not, write to the Free Software
     15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
     16 *
     17 * Author: Nadia Derbey <Nadia.Derbey (at) bull.net>
     18 *
     19 * Check mqns isolation: child mqns cannot be accessed from father
     20 *
     21 * Mount mqueue fs
     22 * unshare
     23 * In unshared process:
     24 *    Mount newinstance mqueuefs
     25 *    Create a posix mq -->mq1
     26 * Check that mq1 is not readable from father
     27 *
     28 * Changelog:
     29 *	Dec 16: accomodate new mqns semantics (Serge Hallyn)
     30 
     31 ***************************************************************************/
     32 
     33 #ifndef _GNU_SOURCE
     34 #define _GNU_SOURCE
     35 #endif
     36 #include <sys/wait.h>
     37 #include <errno.h>
     38 #include <stdio.h>
     39 #include <stdlib.h>
     40 #include <string.h>
     41 #include <unistd.h>
     42 #include "mqns.h"
     43 #include "mqns_helper.h"
     44 
     45 char *TCID = "posixmq_namespace_02";
     46 int TST_TOTAL = 1;
     47 
     48 int p1[2];
     49 int p2[2];
     50 
     51 int check_mqueue(void *vtest)
     52 {
     53 	char buf[30];
     54 	mqd_t mqd;
     55 
     56 	(void) vtest;
     57 
     58 	close(p1[1]);
     59 	close(p2[0]);
     60 
     61 	if (read(p1[0], buf, 3) < 0) {
     62 		perror("read(p1[0], ..) failed");
     63 		exit(1);
     64 	} else {
     65 
     66 		mqd =
     67 		    ltp_syscall(__NR_mq_open, NOSLASH_MQ1,
     68 			    O_RDWR | O_CREAT | O_EXCL, 0777, NULL);
     69 		if (mqd == -1) {
     70 			if (write(p2[1], "mqfail", strlen("mqfail") + 1) < 0) {
     71 				perror("write(p2[1], \"mqfail\", ..) failed");
     72 				exit(1);
     73 			}
     74 		} else {
     75 
     76 			if (write(p2[1], "mqopen", strlen("mqopen") + 1) < 0) {
     77 				perror("write(p2[1], \"mqopen\", ..) failed");
     78 				exit(1);
     79 			} else {
     80 
     81 				if (read(p1[0], buf, 5) < 0) {
     82 					perror("read(p1[0], ..) failed");
     83 					exit(1);
     84 				} else {
     85 
     86 					/* destroy the mqueue */
     87 					if (mq_close(mqd) < 0) {
     88 						perror("mq_close(mqd) failed");
     89 						exit(1);
     90 					} else if (ltp_syscall(__NR_mq_unlink,
     91 							   NOSLASH_MQ1) < 0) {
     92 						perror("mq_unlink(" NOSLASH_MQ1
     93 						       ") failed");
     94 						exit(1);
     95 					} else if (write(p2[1], "done",
     96 							 strlen("done") + 1)
     97 						   < 0) {
     98 						perror("write(p2[1], "
     99 						       "\"done\", ..) failed");
    100 						exit(1);
    101 					}
    102 
    103 				}
    104 
    105 			}
    106 
    107 		}
    108 
    109 	}
    110 	exit(0);
    111 
    112 }
    113 
    114 static void setup(void)
    115 {
    116 	tst_require_root();
    117 	check_mqns();
    118 }
    119 
    120 int main(int argc, char *argv[])
    121 {
    122 	int r;
    123 	mqd_t mqd;
    124 	char buf[30];
    125 	int use_clone = T_UNSHARE;
    126 
    127 	setup();
    128 
    129 	if (argc == 2 && strcmp(argv[1], "-clone") == 0) {
    130 		tst_resm(TINFO,
    131 			 "Testing posix mq namespaces through clone(2).");
    132 		use_clone = T_CLONE;
    133 	} else
    134 		tst_resm(TINFO,
    135 			 "Testing posix mq namespaces through unshare(2).");
    136 
    137 	if (pipe(p1) == -1 || pipe(p2) == -1) {
    138 		tst_brkm(TBROK | TERRNO, NULL, "pipe");
    139 	}
    140 
    141 	/* fire off the test */
    142 	r = do_clone_unshare_test(use_clone, CLONE_NEWIPC, check_mqueue, NULL);
    143 	if (r < 0) {
    144 		tst_brkm(TFAIL, NULL, "failed clone/unshare");
    145 	}
    146 
    147 	tst_resm(TINFO, "Checking namespaces isolation (child to parent)");
    148 
    149 	close(p1[0]);
    150 	close(p2[1]);
    151 	if (write(p1[1], "go", strlen("go") + 1) < 0) {
    152 		tst_brkm(TBROK, NULL, "write(p1[1], \"go\", ..) failed");
    153 	}
    154 
    155 	if (read(p2[0], buf, 7) < 0) {
    156 		tst_resm(TBROK | TERRNO, "read(p2[0], ..) failed");
    157 	} else if (!strcmp(buf, "mqfail")) {
    158 		tst_resm(TFAIL, "child process could not create mqueue");
    159 		umount(DEV_MQUEUE);
    160 	} else if (strcmp(buf, "mqopen")) {
    161 		tst_resm(TFAIL, "child process could not create mqueue");
    162 		umount(DEV_MQUEUE);
    163 	} else {
    164 		mqd = ltp_syscall(__NR_mq_open, NOSLASH_MQ1, O_RDONLY);
    165 		if (mqd == -1) {
    166 			tst_resm(TPASS,
    167 				 "Parent process can't see the mqueue");
    168 		} else {
    169 			tst_resm(TFAIL | TERRNO,
    170 				 "Parent process found mqueue");
    171 			mq_close(mqd);
    172 		}
    173 		if (write(p1[1], "cont", 5) < 0) {
    174 			tst_resm(TBROK | TERRNO, "write(p1[1], ..) failed");
    175 		}
    176 		read(p2[0], buf, 7);
    177 	}
    178 
    179 	tst_exit();
    180 }
    181