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 "test.h"
     35 #include "safe_macros.h"
     36 #include "libclone.h"
     37 #include "pidns_helper.h"
     38 
     39 #define PROCDIR "proc"
     40 char *TCID = "pidns03";
     41 int TST_TOTAL	= 1;
     42 
     43 
     44 static void cleanup(void)
     45 {
     46 	tst_rmdir();
     47 }
     48 
     49 static void setup(void)
     50 {
     51 	tst_require_root();
     52 	check_newpid();
     53 	tst_tmpdir();
     54 	SAFE_MKDIR(cleanup, PROCDIR, 0555);
     55 }
     56 
     57 int child_func(void *arg)
     58 {
     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 	if (readlink(PROCDIR"/self", buf, sizeof(buf)) == -1) {
     68 		perror("readlink");
     69 		umount(PROCDIR);
     70 		return 1;
     71 	}
     72 
     73 	umount(PROCDIR);
     74 
     75 	/* child should have PID 1 in a new pid namespace - if true
     76 	 * procfs belongs to the new pid namespace */
     77 	if (strcmp(buf, "1")) {
     78 		fprintf(stderr, "%s contains: %s\n", PROCDIR"/self", buf);
     79 		return 1;
     80 	}
     81 
     82 	return 0;
     83 }
     84 
     85 static void test(void)
     86 {
     87 	int status;
     88 
     89 	if (do_clone_tests(CLONE_NEWPID, child_func, NULL, NULL, NULL) == -1)
     90 		tst_brkm(TBROK | TERRNO, cleanup, "clone failed");
     91 
     92 	SAFE_WAIT(cleanup, &status);
     93 
     94 	if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
     95 		tst_resm(TPASS, "mounting procfs in a new namespace");
     96 		return;
     97 	}
     98 
     99 	if (WIFSIGNALED(status)) {
    100 		tst_resm(TFAIL, "child was killed with signal %s",
    101 			 tst_strsig(WTERMSIG(status)));
    102 		return;
    103 	}
    104 
    105 	tst_resm(TFAIL, "mounting procfs in a new namespace");
    106 }
    107 
    108 int main(int argc, char *argv[])
    109 {
    110 	int lc;
    111 
    112 	tst_parse_opts(argc, argv, NULL, NULL);
    113 
    114 	setup();
    115 
    116 	for (lc = 0; TEST_LOOPING(lc); lc++)
    117 		test();
    118 
    119 	cleanup();
    120 	tst_exit();
    121 }
    122