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: father mqns cannot be accessed from newinstance
     20 *
     21 * Mount mqueue fs
     22 * Create a posix mq -->mq1
     23 * unshare
     24 * In unshared process:
     25 *    Mount newinstance mqueuefs
     26 *    Check that mq1 is not readable from new ns
     27 
     28 ***************************************************************************/
     29 
     30 #ifndef _GNU_SOURCE
     31 #define _GNU_SOURCE
     32 #endif
     33 #include <sys/wait.h>
     34 #include <errno.h>
     35 #include <stdio.h>
     36 #include <stdlib.h>
     37 #include <string.h>
     38 #include <unistd.h>
     39 #include "mqns.h"
     40 #include "mqns_helper.h"
     41 
     42 char *TCID = "posixmq_namespace_01";
     43 int TST_TOTAL = 1;
     44 
     45 int p1[2];
     46 int p2[2];
     47 
     48 int check_mqueue(void *vtest)
     49 {
     50 	char buf[30];
     51 	mqd_t mqd;
     52 
     53 	(void) vtest;
     54 
     55 	close(p1[1]);
     56 	close(p2[0]);
     57 
     58 	if (read(p1[0], buf, strlen("go") + 1) < 0) {
     59 		printf("read(p1[0], ...) failed: %s\n", strerror(errno));
     60 		exit(1);
     61 	}
     62 	mqd = ltp_syscall(__NR_mq_open, NOSLASH_MQ1, O_RDONLY);
     63 	if (mqd == -1) {
     64 		if (write(p2[1], "notfnd", strlen("notfnd") + 1) < 0) {
     65 			perror("write(p2[1], ...) failed");
     66 			exit(1);
     67 		}
     68 	} else {
     69 		if (write(p2[1], "exists", strlen("exists") + 1) < 0) {
     70 			perror("write(p2[1], \"exists\", 7) failed");
     71 			exit(1);
     72 		} else if (mq_close(mqd) < 0) {
     73 			perror("mq_close(mqd) failed");
     74 			exit(1);
     75 		}
     76 	}
     77 
     78 	exit(0);
     79 }
     80 
     81 static void setup(void)
     82 {
     83 	tst_require_root();
     84 	check_mqns();
     85 }
     86 
     87 int main(int argc, char *argv[])
     88 {
     89 	int r;
     90 	mqd_t mqd;
     91 	char buf[30];
     92 	int use_clone = T_UNSHARE;
     93 
     94 	setup();
     95 
     96 	if (argc == 2 && strcmp(argv[1], "-clone") == 0) {
     97 		tst_resm(TINFO,
     98 			 "Testing posix mq namespaces through clone(2).");
     99 		use_clone = T_CLONE;
    100 	} else
    101 		tst_resm(TINFO,
    102 			 "Testing posix mq namespaces through unshare(2).");
    103 
    104 	if (pipe(p1) == -1 || pipe(p2) == -1) {
    105 		tst_brkm(TBROK | TERRNO, NULL, "pipe failed");
    106 	}
    107 
    108 	mqd = ltp_syscall(__NR_mq_open, NOSLASH_MQ1, O_RDWR | O_CREAT | O_EXCL,
    109 		0777, NULL);
    110 	if (mqd == -1) {
    111 		perror("mq_open");
    112 		tst_brkm(TFAIL, NULL, "mq_open failed");
    113 	}
    114 
    115 	tst_resm(TINFO, "Checking namespaces isolation from parent to child");
    116 	/* fire off the test */
    117 	r = do_clone_unshare_test(use_clone, CLONE_NEWIPC, check_mqueue, NULL);
    118 	if (r < 0) {
    119 		tst_resm(TFAIL, "failed clone/unshare");
    120 		mq_close(mqd);
    121 		ltp_syscall(__NR_mq_unlink, NOSLASH_MQ1);
    122 		tst_exit();
    123 	}
    124 
    125 	close(p1[0]);
    126 	close(p2[1]);
    127 	if (write(p1[1], "go", strlen("go") + 1) < 0)
    128 		tst_resm(TBROK | TERRNO, "write(p1[1], \"go\", ...) failed");
    129 	else if (read(p2[0], buf, 7) < 0)
    130 		tst_resm(TBROK | TERRNO, "read(p2[0], buf, ...) failed");
    131 	else {
    132 		if (!strcmp(buf, "exists")) {
    133 			tst_resm(TFAIL, "child process found mqueue");
    134 		} else if (!strcmp(buf, "notfnd")) {
    135 			tst_resm(TPASS, "child process didn't find mqueue");
    136 		} else {
    137 			tst_resm(TFAIL, "UNKNOWN RESULT");
    138 		}
    139 	}
    140 
    141 	/* destroy the mqueue */
    142 	if (mq_close(mqd) == -1) {
    143 		tst_brkm(TBROK | TERRNO, NULL, "mq_close failed");
    144 	}
    145 	ltp_syscall(__NR_mq_unlink, NOSLASH_MQ1);
    146 
    147 	tst_exit();
    148 }
    149