diff --git a/test/zdtm/static/session04.c b/test/zdtm/static/session04.c index 007ebe403..155480ff3 100644 --- a/test/zdtm/static/session04.c +++ b/test/zdtm/static/session04.c @@ -2,11 +2,16 @@ #include #include #include +#include +#include #include #include #include #include #include +#include +#include +#include #include "zdtmtst.h" @@ -22,7 +27,7 @@ struct process }; struct process *processes; -int nr_processes = 20; +int nr_processes = 21; int current = 0; static void cleanup() @@ -40,6 +45,7 @@ enum commands TEST_SETSID, TEST_DIE, TEST_GETSID, + TEST_SETNS, }; struct command @@ -94,6 +100,79 @@ static int make_child(int id, int flags) return cid; } +static int open_proc(void) +{ + int fd; + char proc_mountpoint[] = "session04_proc.XXXXXX"; + + if (mkdtemp(proc_mountpoint) == NULL) { + pr_perror("mkdtemp failed %s", proc_mountpoint); + return -1; + } + + if (mount("proc", proc_mountpoint, "proc", MS_MGC_VAL | MS_NOSUID | MS_NOEXEC | MS_NODEV, NULL)) { + pr_perror("mount proc failed"); + rmdir(proc_mountpoint); + return -1; + } + + fd = open(proc_mountpoint, O_RDONLY | O_DIRECTORY, 0); + if (fd < 0) + pr_perror("can't open proc"); + + if (umount2(proc_mountpoint, MNT_DETACH)) { + pr_perror("can't umount proc"); + goto err_close; + } + + if (rmdir(proc_mountpoint)) { + pr_perror("can't remove tmp dir"); + goto err_close; + } + + return fd; +err_close: + if (fd >= 0) + close(fd); + return -1; +} + +static int open_pidns(int pid) +{ + int proc, fd; + char pidns_path[PATH_MAX]; + + proc = open_proc(); + if (proc < 0) { + pr_err("open proc"); + return -1; + } + + sprintf(pidns_path, "%d/ns/pid", pid); + fd = openat(proc, pidns_path, O_RDONLY); + if (fd == -1) + pr_err("open pidns fd"); + + close(proc); + return fd; +} + +static int setns_pid(int pid, int nstype) +{ + int pidns, ret; + + pidns = open_pidns(pid); + if (pidns < 0) + return -1; + + ret = setns(pidns, nstype); + if (ret == -1) + pr_perror("setns"); + + close(pidns); + return ret; +} + static void handle_command() { int sk = processes[current].sks[0], ret, status = 0; @@ -150,6 +229,12 @@ static void handle_command() if(status == -1) pr_perror("getsid"); break; + case TEST_SETNS: + test_msg("%3d: setns(%d, %d) = %d\n", current, + cmd.arg1, cmd.arg2, processes[cmd.arg1].pid); + setns_pid(processes[cmd.arg1].pid, cmd.arg2); + + break; case TEST_DIE: test_msg("%3d: die()\n", current); processes[current].dead = 1; @@ -264,6 +349,39 @@ int main(int argc, char ** argv) send_command(7, TEST_DIE, 0, 0); send_command(6, TEST_WAIT, 7, 0); + /* + * Branch of (11,10) - [(12,12)->(13,10)] reparents to init (1,1), + * have session leader but it is not reachable, and branch of + * (16,15) - [(17,15)] reparents to init of second pidns (14,14), + * so have session leader in other pidns. + */ + send_command(1, TEST_FORK, 10, 0); + send_command(10, TEST_SETSID, 0, 0); + send_command(10, TEST_FORK, 11, 0); + send_command(11, TEST_FORK, 12, 0); + send_command(12, TEST_FORK, 13, 0); + send_command(12, TEST_SETSID, 0, 0); + send_command(12, TEST_FORK, 14, CLONE_NEWPID); + send_command(1, TEST_FORK, 15, 0); + send_command(15, TEST_SETSID, 0, 0); + send_command(15, TEST_SETNS, 14, CLONE_NEWPID); + send_command(15, TEST_FORK, 16, 0); + send_command(16, TEST_FORK, 17, 0); + send_command(11, TEST_DIE, 0, 0); + send_command(10, TEST_WAIT, 11, 0); + send_command(16, TEST_DIE, 0, 0); + send_command(15, TEST_WAIT, 16, 0); + + /* + * Add session 15's adopted representative to third pidns + */ + send_command(1, TEST_FORK, 18, CLONE_NEWPID); + send_command(15, TEST_SETNS, 18, CLONE_NEWPID); + send_command(15, TEST_FORK, 19, 0); + send_command(19, TEST_FORK, 20, 0); + send_command(19, TEST_DIE, 0, 0); + send_command(15, TEST_WAIT, 19, 0); + for (i = 0; i < nr_processes; i++) { if (processes[i].dead) continue;