int child_func(void *arg) { int ret = 0; /* makes mount DIRA a slave of DIRA (all slave mounts have * a master mount which is a shared mount) */ if (mount("none", DIRA, "none", MS_SLAVE, NULL) == -1) { perror("mount"); return 1; } TST_SAFE_CHECKPOINT_WAKE_AND_WAIT(NULL, 0); /* checks that shared mounts propagates to slave mount */ if (access(DIRA"/B", F_OK) == -1) ret = 2; TST_SAFE_CHECKPOINT_WAKE_AND_WAIT(NULL, 0); /* bind mounts DIRB to DIRA making contents of DIRB visible * in DIRA */ if (mount(DIRB, DIRA, "none", MS_BIND, NULL) == -1) { perror("mount"); return 1; } TST_SAFE_CHECKPOINT_WAKE_AND_WAIT(NULL, 0); umount(DIRA); return ret; }
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); }
int chld2_msg(void *arg) { int id; struct sysv_msg m; id = msgget(TESTKEY, IPC_CREAT | 0600); if (id == -1) { perror("msgget"); return 2; } m.mtype = 2; m.mtext[0] = 'B'; if (msgsnd(id, &m, sizeof(struct sysv_msg) - sizeof(long), 0) == -1) { perror("msgsnd"); msgctl(id, IPC_RMID, NULL); return 2; } /* tell child1 to continue and wait for it */ TST_SAFE_CHECKPOINT_WAKE_AND_WAIT(NULL, 0); msgctl(id, IPC_RMID, NULL); return 0; }
void dochild(void) { int fd; struct flock flocks; #ifdef UCLINUX TST_CHECKPOINT_INIT(NULL); #endif fd = SAFE_OPEN(NULL, filename, O_RDWR); tst_resm(TINFO, "Child locks file"); flocks.l_type = F_WRLCK; flocks.l_whence = SEEK_CUR; flocks.l_start = recstart; flocks.l_len = reclen; if (fcntl(fd, F_SETLKW, &flocks) < 0) tst_brkm(TFAIL, NULL, "child fcntl failed"); TST_SAFE_CHECKPOINT_WAKE_AND_WAIT(NULL, 0); tst_resm(TINFO, "Child unlocks file"); tst_exit(); }
int chld2_shm(void *arg) { int id; 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; } /* wait for child1 to write to his segment */ TST_SAFE_CHECKPOINT_WAIT(NULL, 0); *shmem = 'B'; TST_SAFE_CHECKPOINT_WAKE_AND_WAIT(NULL, 0); shmdt(shmem); shmctl(id, IPC_RMID, NULL); return 0; }
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; }
int main(int argc, char *argv[]) { pid_t cpid2; char path[BUFSIZ]; int lc; int fd; tst_parse_opts(argc, argv, NULL, NULL); setup(); for (lc = 0; TEST_LOOPING(lc); lc++) { tst_count = 0; parentuid = geteuid(); parentgid = getegid(); cpid1 = ltp_clone_quick(CLONE_NEWUSER | SIGCHLD, (void *)child_fn1, NULL); if (cpid1 < 0) tst_brkm(TBROK | TERRNO, cleanup, "cpid1 clone failed"); cpid2 = ltp_clone_quick(CLONE_NEWUSER | SIGCHLD, (void *)child_fn2, NULL); if (cpid2 < 0) tst_brkm(TBROK | TERRNO, cleanup, "cpid2 clone failed"); if (setgroupstag == false) { sprintf(path, "/proc/%d/setgroups", cpid1); fd = SAFE_OPEN(cleanup, path, O_WRONLY, 0644); SAFE_WRITE(cleanup, 1, fd, "deny", 4); SAFE_CLOSE(cleanup, fd); sprintf(path, "/proc/%d/setgroups", cpid2); fd = SAFE_OPEN(cleanup, path, O_WRONLY, 0644); SAFE_WRITE(cleanup, 1, fd, "deny", 4); SAFE_CLOSE(cleanup, fd); } updatemap(cpid1, UID_MAP, CHILD1UID, parentuid, cleanup); updatemap(cpid2, UID_MAP, CHILD2UID, parentuid, cleanup); updatemap(cpid1, GID_MAP, CHILD1GID, parentuid, cleanup); updatemap(cpid2, GID_MAP, CHILD2GID, parentuid, cleanup); TST_SAFE_CHECKPOINT_WAKE_AND_WAIT(cleanup, 1); tst_record_childstatus(cleanup, cpid1); tst_record_childstatus(cleanup, cpid2); } cleanup(); tst_exit(); }
int chld1_sem(void *arg) { int id; union semun su; struct sembuf sm; 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 child2 to continue and wait for it to create 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) { perror("semop"); semctl(id, 0, IPC_RMID); return 2; } /* tell child2 to continue and wait for it to lock the semaphore */ TST_SAFE_CHECKPOINT_WAKE_AND_WAIT(NULL, 0); sm.sem_op = 1; semop(id, &sm, 1); semctl(id, 0, IPC_RMID); return 0; }
int child_func(void *arg) { int ret = 0; TST_SAFE_CHECKPOINT_WAIT(NULL, 0); if (access(DIRA"/B", F_OK) == -1) ret = 2; TST_SAFE_CHECKPOINT_WAKE_AND_WAIT(NULL, 0); /* bind mounts DIRB to DIRA making contents of DIRB visible * in DIRA */ if (mount(DIRB, DIRA, "none", MS_BIND, NULL) == -1) { perror("mount"); return 1; } TST_SAFE_CHECKPOINT_WAKE_AND_WAIT(NULL, 0); umount(DIRA); return ret; }
void do_child(void) { int cnt; int sig; /* set up signal handler routine */ for (sig = 1; sig < NUMSIGS; sig++) { if (skip_sig(sig)) continue; if (signal(sig, handle_sigs) == SIG_ERR) { tst_resm(TBROK | TERRNO, "signal() %i(%s) failed", sig, tst_strsig(sig)); } } /* all set up to catch signals, now hold them */ for (cnt = 0, sig = 1; sig < NUMSIGS; sig++) { if (skip_sig(sig)) continue; cnt++; TEST(sighold(sig)); if (TEST_RETURN != 0) { tst_resm(TBROK | TTERRNO, "sighold() %i(%s) failed", sig, tst_strsig(sig)); } } TST_SAFE_CHECKPOINT_WAKE_AND_WAIT(NULL, 0); if (!sigs_catched) { tst_resm(TPASS, "All signals were hold"); tst_exit(); } tst_resm(TFAIL, "Signal handler was executed"); for (sig = 1; sig < NUMSIGS; sig++) { if (sigs_map[sig]) { tst_resm(TINFO, "Signal %i(%s) catched", sig, tst_strsig(sig)); } } tst_exit(); }
static void do_child(void) { int fd; #ifdef UCLINUX TST_CHECKPOINT_INIT(NULL); #endif if ((fd = open(TEST_APP, O_WRONLY)) == -1) { perror("open failed"); exit(1); } TST_SAFE_CHECKPOINT_WAKE_AND_WAIT(NULL, 0); exit(0); }
int main(int argc, char *argv[]) { pid_t cpid2; char path[BUFSIZ]; int lc; int fd; int ret; tst_parse_opts(argc, argv, NULL, NULL); setup(); for (lc = 0; TEST_LOOPING(lc); lc++) { tst_count = 0; parentuid = geteuid(); parentgid = getegid(); cpid1 = ltp_clone_quick(CLONE_NEWUSER | SIGCHLD, (void *)child_fn1, NULL); if (cpid1 < 0) tst_brkm(TBROK | TERRNO, cleanup, "cpid1 clone failed"); cpid2 = ltp_clone_quick(CLONE_NEWUSER | SIGCHLD, (void *)child_fn2, NULL); if (cpid2 < 0) tst_brkm(TBROK | TERRNO, cleanup, "cpid2 clone failed"); if (access("/proc/self/setgroups", F_OK) == 0) { sprintf(path, "/proc/%d/setgroups", cpid1); fd = SAFE_OPEN(cleanup, path, O_WRONLY, 0644); SAFE_WRITE(cleanup, 1, fd, "deny", 4); SAFE_CLOSE(cleanup, fd); /* If the setgroups file has the value "deny", * then the setgroups(2) system call can't * subsequently be reenabled (by writing "allow" to * the file) in this user namespace. (Attempts to * do so will fail with the error EPERM.) */ /* test that setgroups can't be re-enabled */ fd = SAFE_OPEN(cleanup, path, O_WRONLY, 0644); ret = write(fd, "allow", 5); if (ret != -1) { tst_brkm(TBROK | TERRNO, cleanup, "write action should fail"); } else if (errno != EPERM) { tst_brkm(TBROK | TERRNO, cleanup, "unexpected error: \n"); } SAFE_CLOSE(cleanup, fd); tst_resm(TPASS, "setgroups can't be re-enabled"); sprintf(path, "/proc/%d/setgroups", cpid2); fd = SAFE_OPEN(cleanup, path, O_WRONLY, 0644); SAFE_WRITE(cleanup, 1, fd, "deny", 4); SAFE_CLOSE(cleanup, fd); } updatemap(cpid1, UID_MAP, CHILD1UID, parentuid, cleanup); updatemap(cpid2, UID_MAP, CHILD2UID, parentuid, cleanup); updatemap(cpid1, GID_MAP, CHILD1GID, parentgid, cleanup); updatemap(cpid2, GID_MAP, CHILD2GID, parentgid, cleanup); TST_SAFE_CHECKPOINT_WAKE_AND_WAIT(cleanup, 1); tst_record_childstatus(cleanup, cpid1); tst_record_childstatus(cleanup, cpid2); } cleanup(); tst_exit(); }