zdtm: test for new init reparent handling with tricky setns

Session 15's(20) leader is in first pidns, one it's process is in
second pidns and one is
in the third. So we create two helpers here for each aditional
pidns.

(It is critical that

Full test now looks like (mind pids here are different(real) from
their id's in source code e.g. 15 is 20 here):
      (pid,ppid,sid)
session04(1, 0, 1)───session04(4, 1, 4)───session04(5, 4, 4)───session04(6, 5, 6,pid1)─┬─session04(8, 6, 8)───session04(9, 8, 7)
                                                                                       ├─session04(10, 6, 6)───session04(11, 10, 11)
                                                                                       ├─session04(13, 6, 13)───session04(14, 13, 11)
                                                                                       ├─session04(15, 6, 15)
                                                                                       ├─session04(17, 6, 17)─┬─session04(18, 17, 15)
                                                                                       │                      └─session04(19, 17, 17,pid2)───session04(22, 19, 20)
                                                                                       ├─session04(20, 6, 20)
                                                                                       └─session04(23, 6, 6,pid3)───session04(25, 23, 20)

Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
This commit is contained in:
Pavel Tikhomirov 2017-05-26 20:02:54 +03:00 committed by Andrei Vagin
parent 55cd96cfd6
commit 0020399593

View file

@ -2,11 +2,16 @@
#include <sched.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <limits.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <sys/prctl.h>
#include <sys/user.h>
#include <sys/mount.h>
#include <sys/types.h>
#include <sys/stat.h>
#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;