void test_init(int argc, char **argv) { pid_t pid; char *val; struct sigaction sa = { .sa_handler = sig_hand, .sa_flags = SA_RESTART, }; sigemptyset(&sa.sa_mask); parseargs(argc, argv); val = getenv("ZDTM_NEWNS"); if (val) { if (!strcmp(val, "1")) { ns_create(argc, argv); exit(1); } if (!strcmp(val, "2")) { test_log_init(outfile, "ns"); redir_stdfds(); ns_init(argc, argv); } } val = getenv("ZDTM_GROUPS"); if (val) { char *tok = NULL; unsigned int size = 0, groups[NGROUPS_MAX]; tok = strtok(val, " "); while (tok) { size++; groups[size - 1] = atoi(tok); tok = strtok(NULL, " "); } if (setgroups(size, groups)) { fprintf(stderr, "Can't set groups: %m"); exit(1); } } val = getenv("ZDTM_GID"); if (val && (setgid(atoi(val)) == -1)) { fprintf(stderr, "Can't set gid: %m"); exit(1); } val = getenv("ZDTM_UID"); if (val && (setuid(atoi(val)) == -1)) { fprintf(stderr, "Can't set gid: %m"); exit(1); } if (prctl(PR_SET_DUMPABLE, 1)) { fprintf(stderr, "Can't set the dumpable flag"); exit(1); } if (sigaction(SIGTERM, &sa, NULL)) { fprintf(stderr, "Can't set SIGTERM handler: %m\n"); exit(1); } if (sigaction(SIGCHLD, &sa, NULL)) { fprintf(stderr, "Can't set SIGCHLD handler: %m\n"); exit(1); } setup_outfile(); redir_stdfds(); pid = fork(); if (pid < 0) { pr_perror("Daemonizing failed"); exit(1); } if (pid) { /* parent will exit when the child is ready */ test_waitsig(); if (futex_get(&sig_received) == SIGCHLD) { int ret; if (waitpid(pid, &ret, 0) != pid) { pr_perror("Unable to wait %d, pid"); exit(1); } if (WIFEXITED(ret)) { pr_err("Test exited unexpectedly with code %d\n", WEXITSTATUS(ret)); exit(1); } if (WIFSIGNALED(ret)) { pr_err("Test exited on unexpected signal %d\n", WTERMSIG(ret)); exit(1); } } if (write_pidfile(pid)) exit(1); _exit(0); } if (setsid() < 0) { pr_perror("Can't become session group leader"); exit(1); } /* record the test pid to remember the ownership of the pidfile */ master_pid = getpid(); sa.sa_handler = SIG_DFL; if (sigaction(SIGCHLD, &sa, NULL)) { pr_perror("Can't reset SIGCHLD handler"); exit(1); } srand48(time(NULL)); /* just in case we need it */ }
void test_init(int argc, char **argv) { pid_t pid; static FILE *pidf; char *val; struct sigaction sa = { .sa_handler = sig_hand, .sa_flags = SA_RESTART, }; sigemptyset(&sa.sa_mask); parseargs(argc, argv); val = getenv("ZDTM_NEWNS"); if (val) { unsetenv("ZDTM_NEWNS"); ns_create(argc, argv); exit(1); } val = getenv("ZDTM_EXE"); if (val) { test_log_init(outfile, "ns"); redir_stdfds(); unsetenv("ZDTM_EXE"); ns_init(argc, argv); exit(1); } val = getenv("ZDTM_GID"); if (val && (setgid(atoi(val)) == -1)) { fprintf(stderr, "Can't set gid: %m"); exit(1); } val = getenv("ZDTM_UID"); if (val && (setuid(atoi(val)) == -1)) { fprintf(stderr, "Can't set gid: %m"); exit(1); } if (sigaction(SIGTERM, &sa, NULL)) { fprintf(stderr, "Can't set SIGTERM handler: %m\n"); exit(1); } if (sigaction(SIGCHLD, &sa, NULL)) { fprintf(stderr, "Can't set SIGCHLD handler: %m\n"); exit(1); } setup_outfile(); redir_stdfds(); pidf = fopen(pidfile, "wx"); if (!pidf) { err("Can't create pid file %s: %m\n", pidfile); exit(1); } pid = fork(); if (pid < 0) { err("Daemonizing failed: %m\n"); exit(1); } if (pid) { /* parent will exit when the child is ready */ test_waitsig(); if (futex_get(&sig_received) == SIGCHLD) { int ret; waitpid(pid, &ret, 0); if (WIFEXITED(ret)) { err("Test exited with unexpectedly with code %d\n", WEXITSTATUS(ret)); exit(0); } if (WIFSIGNALED(ret)) { err("Test exited on unexpected signal %d\n", WTERMSIG(ret)); exit(0); } } fprintf(pidf, "%d\n", pid); fclose(pidf); _exit(0); } /* record the test pid to remember the ownership of the pidfile */ master_pid = getpid(); fclose(pidf); sa.sa_handler = SIG_DFL; if (sigaction(SIGCHLD, &sa, NULL)) { err("Can't reset SIGCHLD handler: %m\n"); exit(1); } if (setsid() < 0) { err("Can't become session group leader: %m\n"); exit(1); } srand48(time(NULL)); /* just in case we need it */ }
static int test_fn(int argc, char **argv) { FILE *f; int fd, tmpfs_fd; unsigned fs_cnt, fs_cnt_last = 0; again: fs_cnt = 0; f = fopen("/proc/self/mountinfo", "r"); if (!f) { fail("Can't open mountinfo"); return -1; } while (fgets(buf, sizeof(buf), f) != NULL) { char *mp = buf, *end; mp = strchr(mp, ' ') + 1; mp = strchr(mp, ' ') + 1; mp = strchr(mp, ' ') + 1; mp = strchr(mp, ' ') + 1; end = strchr(mp, ' '); *end = '\0'; if (!strcmp(mp, "/")) continue; if (!strcmp(mp, "/proc")) continue; umount(mp); fs_cnt++; } fclose(f); if (fs_cnt == 0) goto done; if (fs_cnt != fs_cnt_last) { fs_cnt_last = fs_cnt; goto again; } fail("Can't umount all the filesystems"); return -1; done: rmdir(MPTS_ROOT); if (mkdir(MPTS_ROOT, 0600) < 0) { fail("Can't make zdtm_sys"); return 1; } if (mount("none", MPTS_ROOT, "sysfs", 0, "") < 0) { fail("Can't mount sysfs"); return 1; } if (mount("none", MPTS_ROOT"/dev", "tmpfs", 0, "") < 0) { fail("Can't mount tmpfs"); return 1; } tmpfs_fd = open(MPTS_ROOT"/dev/test", O_WRONLY | O_CREAT); if (write(tmpfs_fd, "hello", 5) <= 0) { err("write() failed"); return 1; } if (mount("none", MPTS_ROOT"/kernel", "proc", 0, "") < 0) { fail("Can't mount proc"); return 1; } if (mount("none", MPTS_ROOT"/kernel/sys/fs/binfmt_misc", "binfmt_misc", 0, "") < 0) { fail("Can't mount proc"); return 1; } mknod("/dev/null", 0777 | S_IFCHR, makedev(1, 3)); setup_outfile(); fd = open(MPTS_ROOT"/kernel/meminfo", O_RDONLY); if (fd == -1) return 1; test_daemon(); test_waitsig(); /* this checks both -- sys and proc presence */ if (access(MPTS_ROOT"/kernel/meminfo", F_OK)) { fail("No proc after restore"); return 1; } pass(); return 0; }