/* Copyright (c) 2014 Red Hat, Inc. All rights reserved. * * This program is free software: you can redistribute it and/or modify * it under the terms of version 2 the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. *********************************************************************** * File: pidns03.c * * Description: * Clones a new child process with CLONE_NEWPID flag - the new child * process mounts procfs to a "proc" directory and checks if it belongs * to a new pid namespace by: * 1. reading value of "proc/self", which is symlink * to directory named after current pid number * 2. comparing read value (PID) with "1" */ #define _GNU_SOURCE #include <sys/wait.h> #include <sys/mount.h> #include <sys/types.h> #include <stdio.h> #include <string.h> #include <unistd.h> #include <errno.h> #include "pidns_helper.h" #include "test.h" #include "safe_macros.h" #define PROCDIR "proc" char *TCID = "pidns03"; int TST_TOTAL = 1; static void cleanup(void) { tst_rmdir(); } static void setup(void) { tst_require_root(); check_newpid(); tst_tmpdir(); SAFE_MKDIR(cleanup, PROCDIR, 0555); } int child_func(void *arg) { ssize_t r; char buf[10]; if (mount("none", PROCDIR, "proc", MS_RDONLY, NULL) == -1) { perror("mount"); return 1; } /* self is symlink to directory named after current pid number */ r = readlink(PROCDIR"/self", buf, sizeof(buf)-1); if (r == -1) { perror("readlink"); umount(PROCDIR); return 1; } buf[r] = '\0'; umount(PROCDIR); /* child should have PID 1 in a new pid namespace - if true * procfs belongs to the new pid namespace */ if (strcmp(buf, "1")) { fprintf(stderr, "%s contains: %s\n", PROCDIR"/self", buf); return 1; } return 0; } static void test(void) { int status; if (do_clone_tests(CLONE_NEWPID, child_func, NULL, NULL, NULL) == -1) tst_brkm(TBROK | TERRNO, cleanup, "clone failed"); SAFE_WAIT(cleanup, &status); if (WIFEXITED(status) && WEXITSTATUS(status) == 0) { tst_resm(TPASS, "mounting procfs in a new namespace"); return; } if (WIFSIGNALED(status)) { tst_resm(TFAIL, "child was killed with signal %s", tst_strsig(WTERMSIG(status))); return; } tst_resm(TFAIL, "mounting procfs in a new namespace"); } int main(int argc, char *argv[]) { int lc; tst_parse_opts(argc, argv, NULL, NULL); setup(); for (lc = 0; TEST_LOOPING(lc); lc++) test(); cleanup(); tst_exit(); }