int chld1_shm(void *arg) { int id, rval = 0; char *shmem; id = shmget(TESTKEY, SHMSIZE, IPC_CREAT); if (id == -1) { perror("shmget"); return 2; } if ((shmem = shmat(id, NULL, 0)) == (char *) -1) { perror("shmat"); shmctl(id, IPC_RMID, NULL); return 2; } *shmem = 'A'; TST_SAFE_CHECKPOINT_WAKE_AND_WAIT(NULL, 0); /* if child1 shared segment has changed (by child2) report fail */ if (*shmem != 'A') rval = 1; /* tell child2 to continue */ TST_SAFE_CHECKPOINT_WAKE(NULL, 0); shmdt(shmem); shmctl(id, IPC_RMID, NULL); return rval; }
static void test(void) { int status; /* unshares the mount ns */ if (unshare(CLONE_NEWNS) == -1) tst_brkm(TBROK | TERRNO, cleanup, "unshare failed"); /* makes sure parent mounts/umounts have no effect on a real system */ SAFE_MOUNT(cleanup, "none", "/", "none", MS_REC|MS_PRIVATE, NULL); /* bind mounts DIRA to itself */ SAFE_MOUNT(cleanup, DIRA, DIRA, "none", MS_BIND, NULL); /* makes mount DIRA shared */ SAFE_MOUNT(cleanup, "none", DIRA, "none", MS_SHARED, NULL); if (do_clone_tests(CLONE_NEWNS, child_func, NULL, NULL, NULL) == -1) tst_brkm(TBROK | TERRNO, cleanup, "clone failed"); /* waits for child to make a slave mount */ TST_SAFE_CHECKPOINT_WAIT(cleanup, 0); /* bind mounts DIRB to DIRA making contents of DIRB visible * in DIRA */ SAFE_MOUNT(cleanup, DIRB, DIRA, "none", MS_BIND, NULL); TST_SAFE_CHECKPOINT_WAKE_AND_WAIT(cleanup, 0); SAFE_UMOUNT(cleanup, DIRA); TST_SAFE_CHECKPOINT_WAKE_AND_WAIT(cleanup, 0); /* checks that slave mount doesn't propagate to shared mount */ if ((access(DIRA"/A", F_OK) == 0) && (access(DIRA"/B", F_OK) == -1)) tst_resm(TPASS, "propagation from slave mount passed"); else tst_resm(TFAIL, "propagation form slave mount failed"); TST_SAFE_CHECKPOINT_WAKE(cleanup, 0); SAFE_WAIT(cleanup, &status); if (WIFEXITED(status)) { if (WEXITSTATUS(status) == 0) tst_resm(TPASS, "propagation to slave mount passed"); else tst_resm(TFAIL, "propagation to slave mount failed"); } if (WIFSIGNALED(status)) { tst_resm(TBROK, "child was killed with signal %s", tst_strsig(WTERMSIG(status))); return; } SAFE_UMOUNT(cleanup, DIRA); }
static void do_child(void) { int fd, offset; char buf[FS_BLOCKSIZE]; char *addr = NULL; /* * We have changed SIGBUS' handler in parent process by calling * tst_sig(FORK, DEF_HANDLER, NULL), so here just restore it. */ if (signal(SIGBUS, SIG_DFL) == SIG_ERR) tst_brkm(TBROK | TERRNO, NULL, "signal(SIGBUS) failed"); memset(buf, 'a', FS_BLOCKSIZE); fd = SAFE_OPEN(NULL, "testfilec", O_RDWR); SAFE_PWRITE(NULL, 1, fd, buf, FS_BLOCKSIZE, 0); /* * In case mremap() may fail because that memory area can not be * expanded at current virtual address(MREMAP_MAYMOVE is not set), * we first do a mmap(page_size * 2) operation to reserve some * free address space. */ addr = SAFE_MMAP(NULL, NULL, page_size * 2, PROT_WRITE | PROT_READ, MAP_PRIVATE_EXCEPT_UCLINUX | MAP_ANONYMOUS, -1, 0); SAFE_MUNMAP(NULL, addr, page_size * 2); addr = SAFE_MMAP(NULL, addr, FS_BLOCKSIZE, PROT_WRITE | PROT_READ, MAP_SHARED, fd, 0); addr[0] = 'a'; SAFE_FTRUNCATE(NULL, fd, page_size * 2); addr = mremap(addr, FS_BLOCKSIZE, 2 * page_size, 0); if (addr == MAP_FAILED) tst_brkm(TBROK | TERRNO, NULL, "mremap failed unexpectedly"); /* * Let parent process consume FS free blocks as many as possible, then * there'll be no free blocks allocated for this new file mmaping for * offset starting at 1024, 2048, or 3072. If this above kernel bug * has been fixed, usually child process will killed by SIGBUS signal, * if not, the data 'A', 'B', 'C' will be silently discarded later when * kernel writepage is called, that means data corruption. */ TST_SAFE_CHECKPOINT_WAKE(NULL, 0); TST_SAFE_CHECKPOINT_WAIT(NULL, 0); for (offset = FS_BLOCKSIZE; offset < page_size; offset += FS_BLOCKSIZE) addr[offset] = 'a'; SAFE_MUNMAP(NULL, addr, 2 * page_size); SAFE_CLOSE(NULL, fd); exit(TFAIL); }
int main(void) { TST_CHECKPOINT_INIT(NULL); TST_SAFE_CHECKPOINT_WAKE(NULL, 0); for (;;) { sleep(1); } return 0; }
int main(int argc, char *argv[]) { int status; int lc; int childpid; int parentuid; int parentgid; char path[BUFSIZ]; char content[BUFSIZ]; int fd; tst_parse_opts(argc, argv, NULL, NULL); setup(); for (lc = 0; TEST_LOOPING(lc); lc++) { tst_count = 0; childpid = ltp_clone_quick(CLONE_NEWUSER | SIGCHLD, (void *)child_fn1, NULL); if (childpid < 0) tst_brkm(TFAIL | TERRNO, cleanup, "clone failed"); parentuid = geteuid(); parentgid = getegid(); sprintf(path, "/proc/%d/uid_map", childpid); sprintf(content, "100 %d 1", parentuid); fd = SAFE_OPEN(cleanup, path, O_WRONLY, 0644); SAFE_WRITE(cleanup, 1, fd, content, strlen(content)); SAFE_CLOSE(cleanup, fd); sprintf(path, "/proc/%d/gid_map", childpid); sprintf(content, "100 %d 1", parentgid); fd = SAFE_OPEN(cleanup, path, O_WRONLY, 0644); SAFE_WRITE(cleanup, 1, fd, content, strlen(content)); SAFE_CLOSE(cleanup, fd); TST_SAFE_CHECKPOINT_WAKE(cleanup, 0); if (waitpid(childpid, &status, 0) < 0) tst_brkm(TBROK | TERRNO, cleanup, "waitpid failed"); if (WIFSIGNALED(status)) { tst_resm(TFAIL, "child was killed with signal = %d", WTERMSIG(status)); } else if (WIFEXITED(status) && WEXITSTATUS(status) != 0) tst_resm(TFAIL, "child exited abnormally"); else tst_resm(TPASS, "the uid and the gid are right inside " "the container"); } cleanup(); tst_exit(); }
static void do_child(void) { if (setsid() < 0) { printf("CHILD: setsid() failed, errno: %d\n", errno); exit(2); } TST_SAFE_CHECKPOINT_WAKE(NULL, 0); TST_SAFE_CHECKPOINT_WAIT(NULL, 0); exit(0); }
static void do_test(void) { int fd, ret, status; pid_t child; char buf[FS_BLOCKSIZE]; SAFE_TOUCH(cleanup, "testfilep", 0644, NULL); SAFE_TOUCH(cleanup, "testfilec", 0644, NULL); child = tst_fork(); switch (child) { case -1: tst_brkm(TBROK | TERRNO, cleanup, "fork failed"); case 0: do_child(); default: fd = SAFE_OPEN(cleanup, "testfilep", O_RDWR); memset(buf, 'a', FS_BLOCKSIZE); TST_SAFE_CHECKPOINT_WAIT(cleanup, 0); while (1) { ret = write(fd, buf, FS_BLOCKSIZE); if (ret < 0) { if (errno == ENOSPC) { break; } else { tst_brkm(TBROK | TERRNO, cleanup, "write failed unexpectedly"); } } } SAFE_CLOSE(cleanup, fd); TST_SAFE_CHECKPOINT_WAKE(cleanup, 0); } wait(&status); if (WIFEXITED(status) && WEXITSTATUS(status) == 1) { bug_reproduced = 1; } else { /* * If child process was killed by SIGBUS, bug is not reproduced. */ if (!WIFSIGNALED(status) || WTERMSIG(status) != SIGBUS) { tst_brkm(TBROK | TERRNO, cleanup, "child process terminate unexpectedly"); } } SAFE_UNLINK(cleanup, "testfilep"); SAFE_UNLINK(cleanup, "testfilec"); }
int main(int argc, char **argv) { int lc, status; tst_parse_opts(argc, argv, options, &help); setup(); for (lc = 0; TEST_LOOPING(lc); lc++) { tst_count = 0; SAFE_PIPE(cleanup, pipe_fd); /* the start of child_init_and_verify and child_write is * already synchronized via pipe */ pids[0] = fork(); switch (pids[0]) { case -1: tst_brkm(TBROK | TERRNO, cleanup, "fork #0"); case 0: child_init_and_verify(); exit(0); default: break; } pids[1] = fork(); switch (pids[1]) { case -1: tst_brkm(TBROK | TERRNO, cleanup, "fork #1"); case 0: child_write(); exit(0); } /* wait until child_write writes into * child_init_and_verify's VM */ SAFE_WAITPID(cleanup, pids[1], &status, 0); if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) tst_resm(TFAIL, "child 1 returns %d", status); /* signal child_init_and_verify to verify its VM now */ TST_SAFE_CHECKPOINT_WAKE(cleanup, 0); SAFE_WAITPID(cleanup, pids[0], &status, 0); if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) tst_resm(TFAIL, "child 0 returns %d", status); } cleanup(); tst_exit(); }
int chld2_sem(void *arg) { int id, rval = 0; struct sembuf sm; union semun su; /* wait for child1 to create the semaphore */ TST_SAFE_CHECKPOINT_WAIT(NULL, 0); id = semget(TESTKEY, 1, IPC_CREAT); if (id == -1) { perror("semget"); return 2; } su.val = 1; if (semctl(id, 0, SETVAL, su) == -1) { perror("semctl"); semctl(id, 0, IPC_RMID); return 2; } /* tell child1 to continue and wait for it to lock the semaphore */ TST_SAFE_CHECKPOINT_WAKE_AND_WAIT(NULL, 0); sm.sem_num = 0; sm.sem_op = -1; sm.sem_flg = IPC_NOWAIT; if (semop(id, &sm, 1) == -1) { if (errno == EAGAIN) { rval = 1; } else { perror("semop"); semctl(id, 0, IPC_RMID); return 2; } } /* tell child1 to continue */ TST_SAFE_CHECKPOINT_WAKE(NULL, 0); sm.sem_op = 1; semop(id, &sm, 1); semctl(id, 0, IPC_RMID); return rval; }
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(); }
int main(int ac, char **av) { int lc; pid_t pid; char *argv[2] = {TEST_APP, NULL}; char *env[1] = {NULL}; 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()) == -1) { tst_brkm(TBROK, cleanup, "fork failed"); } else if (pid == 0) { #ifdef UCLINUX if (self_exec(av[0], "") < 0) tst_brkm(TBROK, cleanup, "self_exec failed"); #else do_child(); #endif } TST_SAFE_CHECKPOINT_WAIT(cleanup, 0); TEST(execve(TEST_APP, argv, env)); if (TEST_ERRNO != ETXTBSY) tst_resm(TFAIL | TTERRNO, "execve succeeded, expected failure"); else tst_resm(TPASS | TTERRNO, "execve failed as expected"); TST_SAFE_CHECKPOINT_WAKE(cleanup, 0); SAFE_WAIT(cleanup, NULL); } cleanup(); tst_exit(); }
int chld1_msg(void *arg) { int id, n, rval = 0; struct sysv_msg m; struct sysv_msg rec; id = msgget(TESTKEY, IPC_CREAT | 0600); if (id == -1) { perror("msgget"); return 2; } m.mtype = 1; m.mtext[0] = 'A'; if (msgsnd(id, &m, sizeof(struct sysv_msg) - sizeof(long), 0) == -1) { perror("msgsnd"); msgctl(id, IPC_RMID, NULL); return 2; } /* wait for child2 to write into the message queue */ TST_SAFE_CHECKPOINT_WAIT(NULL, 0); /* if child1 message queue has changed (by child2) report fail */ n = msgrcv(id, &rec, sizeof(struct sysv_msg) - sizeof(long), 2, IPC_NOWAIT); if (n == -1 && errno != ENOMSG) { perror("msgrcv"); msgctl(id, IPC_RMID, NULL); return 2; } /* if mtype #2 was found in the message queue, it is fail */ if (n > 0) { rval = 1; } /* tell child2 to continue */ TST_SAFE_CHECKPOINT_WAKE(NULL, 0); msgctl(id, IPC_RMID, NULL); return rval; }
static void test(void) { pid_t pid; int status; /* unshares the network namespace */ if (unshare(CLONE_NEWNET) == -1) tst_brkm(TBROK | TERRNO, cleanup, "unshare failed"); pid = tst_fork(); if (pid < 0) { tst_brkm(TBROK | TERRNO, cleanup, "fork failed"); } if (pid == 0) { _exit(child_func()); } /* creates TAP network interface dummy0 */ if (WEXITSTATUS(system("ip tuntap add dev dummy0 mode tap")) == -1) tst_brkm(TBROK | TERRNO, cleanup, "system failed"); /* removes previously created dummy0 device */ if (WEXITSTATUS(system("ip tuntap del mode tap dummy0")) == -1) tst_brkm(TBROK | TERRNO, cleanup, "system failed"); /* allow child to continue */ TST_SAFE_CHECKPOINT_WAKE(cleanup, 0); SAFE_WAITPID(cleanup, pid, &status, 0); if (WIFEXITED(status) && WEXITSTATUS(status) != 0) { tst_resm(TFAIL, "netlink interface fail"); return; } if (WIFSIGNALED(status)) { tst_resm(TFAIL, "child was killed with signal %s", tst_strsig(WTERMSIG(status))); return; } tst_resm(TPASS, "netlink interface pass"); }
static void doparent(void) { int fd; /* Wait for child lock */ TST_SAFE_CHECKPOINT_WAIT(cleanup, 0); fd = SAFE_OPEN(cleanup, filename, O_RDWR | O_NONBLOCK); ftruncate_expect_fail(fd, RECLEN, "offset before lock"); ftruncate_expect_fail(fd, recstart + RECLEN/2, "offset in lock"); ftruncate_expect_success(fd, recstart + RECLEN, "offset after lock"); /* wake child and wait for it to exit (to free record lock) */ TST_SAFE_CHECKPOINT_WAKE(cleanup, 0); SAFE_WAIT(NULL, NULL); ftruncate_expect_success(fd, recstart + RECLEN/2, "offset in lock"); ftruncate_expect_success(fd, recstart, "offset before lock"); ftruncate_expect_success(fd, recstart + RECLEN, "offset after lock"); SAFE_CLOSE(NULL, fd); }
int main(int ac, char **av) { int child_pid; int status; int rval; 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++) { tst_count = 0; /* Child is in new session we are not alowed to change pgid */ if ((child_pid = FORK_OR_VFORK()) == -1) tst_brkm(TBROK, cleanup, "fork() failed"); if (child_pid == 0) { #ifdef UCLINUX if (self_exec(av[0], "") < 0) tst_brkm(TBROK, cleanup, "self_exec failed"); #else do_child(); #endif } TST_SAFE_CHECKPOINT_WAIT(cleanup, 0); rval = setpgid(child_pid, getppid()); if (rval == -1 && errno == EPERM) { tst_resm(TPASS, "setpgid failed with EPERM"); } else { tst_resm(TFAIL, "retval %d, errno %d, expected errno %d", rval, errno, EPERM); } TST_SAFE_CHECKPOINT_WAKE(cleanup, 0); if (wait(&status) < 0) tst_resm(TFAIL | TERRNO, "wait() for child 1 failed"); if (!(WIFEXITED(status)) || (WEXITSTATUS(status) != 0)) tst_resm(TFAIL, "child 1 failed with status %d", WEXITSTATUS(status)); /* Child after exec() we are no longer allowed to set pgid */ if ((child_pid = FORK_OR_VFORK()) == -1) tst_resm(TFAIL, "Fork failed"); if (child_pid == 0) { if (execlp(TEST_APP, TEST_APP, NULL) < 0) perror("exec failed"); exit(127); } TST_SAFE_CHECKPOINT_WAIT(cleanup, 0); rval = setpgid(child_pid, getppid()); if (rval == -1 && errno == EACCES) { tst_resm(TPASS, "setpgid failed with EACCES"); } else { tst_resm(TFAIL, "retval %d, errno %d, expected errno %d", rval, errno, EACCES); } TST_SAFE_CHECKPOINT_WAKE(cleanup, 0); if (wait(&status) < 0) tst_resm(TFAIL | TERRNO, "wait() for child 2 failed"); if (!(WIFEXITED(status)) || (WEXITSTATUS(status) != 0)) tst_resm(TFAIL, "child 2 failed with status %d", WEXITSTATUS(status)); } cleanup(); tst_exit(); }
/* * child_fn2() - Inside a new user namespace */ static int child_fn2(void) { int exit_val = 0; int uid, gid; char cpid1uidpath[BUFSIZ]; char cpid1gidpath[BUFSIZ]; int idinsidens, idoutsidens, length; TST_SAFE_CHECKPOINT_WAIT(NULL, 1); uid = geteuid(); gid = getegid(); if (uid != CHILD2UID || gid != CHILD2GID) { printf("unexpected uid=%d gid=%d\n", uid, gid); exit_val = 1; } /*Get the uid parameters of the child_fn2 process.*/ SAFE_FILE_SCANF(NULL, "/proc/self/uid_map", "%d %d %d", &idinsidens, &idoutsidens, &length); /* map file format:ID-inside-ns ID-outside-ns length If the process opening the file is in the same user namespace as the process PID, then ID-outside-ns is defined with respect to the parent user namespace.*/ if (idinsidens != CHILD2UID || idoutsidens != parentuid) { printf("child_fn2 checks /proc/cpid2/uid_map:\n"); printf("unexpected: idinsidens=%d idoutsidens=%d\n", idinsidens, idoutsidens); exit_val = 1; } sprintf(cpid1uidpath, "/proc/%d/uid_map", cpid1); SAFE_FILE_SCANF(NULL, cpid1uidpath, "%d %d %d", &idinsidens, &idoutsidens, &length); /* If the process opening the file is in a different user namespace, then ID-outside-ns is defined with respect to the user namespace of the process opening the file.*/ if (idinsidens != CHILD1UID || idoutsidens != CHILD2UID) { printf("child_fn2 checks /proc/cpid1/uid_map:\n"); printf("unexpected: idinsidens=%d idoutsidens=%d\n", idinsidens, idoutsidens); exit_val = 1; } sprintf(cpid1gidpath, "/proc/%d/gid_map", cpid1); SAFE_FILE_SCANF(NULL, "/proc/self/gid_map", "%d %d %d", &idinsidens, &idoutsidens, &length); if (idinsidens != CHILD2GID || idoutsidens != parentgid) { printf("child_fn2 checks /proc/cpid2/gid_map:\n"); printf("unexpected: idinsidens=%d idoutsidens=%d\n", idinsidens, idoutsidens); exit_val = 1; } SAFE_FILE_SCANF(NULL, cpid1gidpath, "%d %d %d", &idinsidens, &idoutsidens, &length); if (idinsidens != CHILD1GID || idoutsidens != CHILD2GID) { printf("child_fn1 checks /proc/cpid1/gid_map:\n"); printf("unexpected: idinsidens=%d idoutsidens=%d\n", idinsidens, idoutsidens); exit_val = 1; } TST_SAFE_CHECKPOINT_WAKE(NULL, 0); TST_SAFE_CHECKPOINT_WAKE(NULL, 1); return exit_val; }
int main(int argc, char **argv) { int lc; pid_t pid; int status; int fd; tst_parse_opts(argc, argv, NULL, NULL); #ifdef UCLINUX maybe_run_child(&childfunc_uc, "ds", &fd_uc, FILE_NAME); #endif setup(); for (lc = 0; TEST_LOOPING(lc); lc++) { tst_count = 0; fd = open(FILE_NAME, O_RDWR); if (fd == -1) tst_brkm(TFAIL, cleanup, "parent failed to open the" "file, errno %d", errno); pid = FORK_OR_VFORK(); if (pid == -1) tst_brkm(TFAIL, cleanup, "fork() failed, errno %d", errno); if (pid == 0) { #ifdef UCLINUX if (self_exec(argv[0], "ds", fd, FILE_NAME) < 0) tst_brkm(TFAIL, cleanup, "self_exec failed, " "errno &d", errno); #else childfunc(fd); #endif } TEST(flock(fd, LOCK_EX | LOCK_NB)); if (TEST_RETURN != 0) tst_resm(TFAIL, "Parent: Initial attempt to flock() failed, " "errno %d", TEST_ERRNO); else tst_resm(TPASS, "Parent: Initial attempt to flock() passed"); TST_SAFE_CHECKPOINT_WAKE(cleanup, 0); if ((waitpid(pid, &status, 0)) < 0) { tst_resm(TFAIL, "wait() failed"); continue; } if ((WIFEXITED(status)) && (WEXITSTATUS(status) == 0)) tst_resm(TPASS, "flock03 Passed"); else tst_resm(TFAIL, "flock03 Failed"); close(fd); } cleanup(); tst_exit(); }