static void do_test(void) { int i; if (!SAFE_FORK()) { SAFE_FILE_PRINTF(PATH_AUTOGROUP, "%d", 1); SAFE_SETSID(); if (SAFE_FORK()) pause(); SAFE_KILL(getppid(), SIGKILL); usleep(1000); // The child has gone, the grandchild runs with kref == 1 SAFE_FILE_PRINTF(PATH_AUTOGROUP, "%d", 0); SAFE_SETSID(); // runs with the freed ag/tg for (i = 0; i < LOOPS; i++) usleep(10); TST_CHECKPOINT_WAKE(0); exit(0); } SAFE_WAIT(NULL); // destroy the child's ag/tg TST_CHECKPOINT_WAIT(0); tst_res(TPASS, "Bug not reproduced"); }
static void verify_creat(void) { pid_t pid; pid = SAFE_FORK(); if (pid == 0) { char *av[] = {TEST_APP, NULL}; (void)execve(TEST_APP, av, tst_ipc_envp); perror("execve failed"); exit(1); } TST_CHECKPOINT_WAIT(0); TEST(creat(TEST_APP, O_WRONLY)); if (TEST_RETURN != -1) { tst_res(TFAIL, "creat() succeeded unexpectedly"); return; } if (TEST_ERRNO == ETXTBSY) tst_res(TPASS, "creat() received EXTBSY"); else tst_res(TFAIL | TTERRNO, "creat() failed unexpectedly"); SAFE_KILL(pid, SIGKILL); SAFE_WAITPID(pid, NULL, 0); }
static void resume_ksm_children(int *child, int num) { int k; tst_res(TINFO, "resume all children."); for (k = 0; k < num; k++) SAFE_KILL(child[k], SIGCONT); fflush(stdout); }
int main(int ac, char **av) { int sig; int lc; tst_parse_opts(ac, av, NULL, NULL); #ifdef UCLINUX maybe_run_child(&do_child, ""); #endif setup(); for (lc = 0; TEST_LOOPING(lc); lc++) { if ((pid = FORK_OR_VFORK()) < 0) { tst_brkm(TBROK | TERRNO, NULL, "fork() failed"); } else if (pid > 0) { TST_SAFE_CHECKPOINT_WAIT(NULL, 0); for (sig = 1; sig < NUMSIGS; sig++) { if (skip_sig(sig)) continue; SAFE_KILL(NULL, pid, sig); } TST_SAFE_CHECKPOINT_WAKE(NULL, 0); tst_record_childstatus(cleanup, pid); } else { #ifdef UCLINUX if (self_exec(av[0], "") < 0) { tst_brkm(TBROK | TERRNO, NULL, "self_exec() failed"); } #else do_child(); #endif } } cleanup(); tst_exit(); }
static void verify_inotify(void) { int inotify_fd, fd; pid_t pid; int i, tests; pid = SAFE_FORK(); if (pid == 0) { while (1) { for (i = 0; i < FILES; i++) { fd = SAFE_OPEN(names[i], O_CREAT | O_RDWR, 0600); SAFE_CLOSE(fd); } for (i = 0; i < FILES; i++) SAFE_UNLINK(names[i]); } } for (tests = 0; tests < TEARDOWNS; tests++) { inotify_fd = myinotify_init1(O_NONBLOCK); if (inotify_fd < 0) tst_brk(TBROK | TERRNO, "inotify_init failed"); for (i = 0; i < FILES; i++) { /* * Both failure and success are fine since * files are being deleted in parallel - this * is what provokes the race we want to test * for... */ myinotify_add_watch(inotify_fd, names[i], IN_MODIFY); } SAFE_CLOSE(inotify_fd); } /* We survived for given time - test succeeded */ tst_res(TPASS, "kernel survived inotify beating"); /* Kill the child creating / deleting files and wait for it */ SAFE_KILL(pid, SIGKILL); SAFE_WAIT(NULL); }
void dirtyc0w_test(void) { int i, fd, pid, fail = 0; char c; /* Create file */ fd = SAFE_OPEN(FNAME, O_WRONLY|O_CREAT|O_EXCL, 0444); SAFE_WRITE(1, fd, STR, sizeof(STR)-1); SAFE_CLOSE(fd); pid = SAFE_FORK(); if (!pid) { SAFE_SETGID(nobody_gid); SAFE_SETUID(nobody_uid); SAFE_EXECLP("dirtyc0w_child", "dirtyc0w_child", NULL); } TST_CHECKPOINT_WAIT(0); for (i = 0; i < 100; i++) { usleep(10000); SAFE_FILE_SCANF(FNAME, "%c", &c); if (c != 't') { fail = 1; break; } } SAFE_KILL(pid, SIGUSR1); tst_reap_children(); SAFE_UNLINK(FNAME); if (fail) tst_res(TFAIL, "Bug reproduced!"); else tst_res(TPASS, "Bug not reproduced"); }
int main(int ac, char **av) { int status; char cur_cwd[PATH_MAX]; pid_t child; tst_parse_opts(ac, av, NULL, NULL); setup(); child = tst_fork(); if (child < 0) tst_brkm(TBROK | TERRNO, cleanup, "fork failed"); if (child == 0) do_child(); while (1) { SAFE_GETCWD(cleanup, cur_cwd, PATH_MAX); if (strncmp(init_cwd, cur_cwd, PATH_MAX)) { tst_resm(TFAIL, "initial current work directory is " "%s, now is %s. Bug is reproduced!", init_cwd, cur_cwd); break; } if (end) { tst_resm(TPASS, "Bug is not reproduced!"); break; } } SAFE_KILL(cleanup, child, SIGKILL); SAFE_WAITPID(cleanup, child, &status, 0); cleanup(); tst_exit(); }
int main(int ac, char **av) { int lc; int i; pid_t pid; void do_child(); tst_parse_opts(ac, av, NULL, NULL); #ifdef UCLINUX maybe_run_child(&do_child_uclinux, "dd", &i_uclinux, &sem_id_1); #endif setup(); /* global setup */ /* The following loop checks looping state if -i option given */ for (lc = 0; TEST_LOOPING(lc); lc++) { /* reset tst_count in case we are looping */ tst_count = 0; for (i = 0; i < TST_TOTAL; i++) { /* initialize the s_buf buffer */ s_buf.sem_op = TC[i].op; s_buf.sem_flg = TC[i].flg; s_buf.sem_num = TC[i].num; /* initialize all of the primitive semaphores */ if (semctl(sem_id_1, TC[i].num, SETVAL, TC[i].semunptr) == -1) { tst_brkm(TBROK, cleanup, "semctl() failed"); } if ((pid = FORK_OR_VFORK()) == -1) { tst_brkm(TBROK, cleanup, "could not fork"); } if (pid == 0) { /* child */ #ifdef UCLINUX if (self_exec(av[0], "dd", i, sem_id_1) < 0) { tst_brkm(TBROK, cleanup, "could not self_exec"); } #else do_child(i); #endif } else { TST_PROCESS_STATE_WAIT(cleanup, pid, 'S'); /* * If we are testing for EIDRM then remove * the semaphore, else send a signal that * must be caught as we are testing for * EINTR. */ if (TC[i].error == EIDRM) { /* remove the semaphore resource */ rm_sema(sem_id_1); } else { SAFE_KILL(cleanup, pid, SIGHUP); } /* let the child carry on */ waitpid(pid, NULL, 0); } /* * recreate the semaphore resource if needed */ if (TC[i].error == EINTR) { continue; } if ((sem_id_1 = semget(semkey, PSEMS, IPC_CREAT | IPC_EXCL | SEM_RA)) == -1) { tst_brkm(TBROK, cleanup, "couldn't recreate " "semaphore"); } } } cleanup(); tst_exit(); }