Home | History | Annotate | Download | only in pidns
      1 /* Copyright (c) 2014 Red Hat, Inc. All rights reserved.
      2  *
      3  * This program is free software: you can redistribute it and/or modify
      4  * it under the terms of version 2 the GNU General Public License as
      5  * published by the Free Software Foundation.
      6  *
      7  * This program is distributed in the hope that it will be useful,
      8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     10  * GNU General Public License for more details.
     11  *
     12  * You should have received a copy of the GNU General Public License
     13  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
     14  ***********************************************************************
     15  * File: pidns03.c
     16  *
     17  * Description:
     18  * Clones a new child process with CLONE_NEWPID flag - the new child
     19  * process mounts procfs to a "proc" directory and checks if it belongs
     20  * to a new pid namespace by:
     21  * 1. reading value of "proc/self", which is symlink
     22  *    to directory named after current pid number
     23  * 2. comparing read value (PID) with "1"
     24  */
     25 
     26 #define _GNU_SOURCE
     27 #include <sys/wait.h>
     28 #include <sys/mount.h>
     29 #include <sys/types.h>
     30 #include <stdio.h>
     31 #include <string.h>
     32 #include <unistd.h>
     33 #include <errno.h>
     34 #include "pidns_helper.h"
     35 #include "test.h"
     36 #include "safe_macros.h"
     37 
     38 #define PROCDIR "proc"
     39 char *TCID = "pidns03";
     40 int TST_TOTAL	= 1;
     41 
     42 
     43 static void cleanup(void)
     44 {
     45 	tst_rmdir();
     46 }
     47 
     48 static void setup(void)
     49 {
     50 	tst_require_root();
     51 	check_newpid();
     52 	tst_tmpdir();
     53 	SAFE_MKDIR(cleanup, PROCDIR, 0555);
     54 }
     55 
     56 int child_func(void *arg)
     57 {
     58 	ssize_t r;
     59 	char buf[10];
     60 
     61 	if (mount("none", PROCDIR, "proc", MS_RDONLY, NULL) == -1) {
     62 		perror("mount");
     63 		return 1;
     64 	}
     65 
     66 	/* self is symlink to directory named after current pid number */
     67 	r = readlink(PROCDIR"/self", buf, sizeof(buf)-1);
     68 	if (r == -1) {
     69 		perror("readlink");
     70 		umount(PROCDIR);
     71 		return 1;
     72 	}
     73 
     74 	buf[r] = '\0';
     75 
     76 	umount(PROCDIR);
     77 
     78 	/* child should have PID 1 in a new pid namespace - if true
     79 	 * procfs belongs to the new pid namespace */
     80 	if (strcmp(buf, "1")) {
     81 		fprintf(stderr, "%s contains: %s\n", PROCDIR"/self", buf);
     82 		return 1;
     83 	}
     84 
     85 	return 0;
     86 }
     87 
     88 static void test(void)
     89 {
     90 	int status;
     91 
     92 	if (do_clone_tests(CLONE_NEWPID, child_func, NULL, NULL, NULL) == -1)
     93 		tst_brkm(TBROK | TERRNO, cleanup, "clone failed");
     94 
     95 	SAFE_WAIT(cleanup, &status);
     96 
     97 	if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
     98 		tst_resm(TPASS, "mounting procfs in a new namespace");
     99 		return;
    100 	}
    101 
    102 	if (WIFSIGNALED(status)) {
    103 		tst_resm(TFAIL, "child was killed with signal %s",
    104 			 tst_strsig(WTERMSIG(status)));
    105 		return;
    106 	}
    107 
    108 	tst_resm(TFAIL, "mounting procfs in a new namespace");
    109 }
    110 
    111 int main(int argc, char *argv[])
    112 {
    113 	int lc;
    114 
    115 	tst_parse_opts(argc, argv, NULL, NULL);
    116 
    117 	setup();
    118 
    119 	for (lc = 0; TEST_LOOPING(lc); lc++)
    120 		test();
    121 
    122 	cleanup();
    123 	tst_exit();
    124 }
    125