[v2,08/57] zdtm: Add pidns00 test

Submitted by Kirill Tkhai on March 28, 2017, 3:35 p.m.

Details

Message ID 149071532437.12770.15653273806508575752.stgit@localhost.localdomain
State New
Series "Nested pid namespaces support"
Headers show

Commit Message

Kirill Tkhai March 28, 2017, 3:35 p.m.
Create parent (P) and its three children (C1, C2 and C3)
with different pid namespaces:

	     P (pid_ns1)
	    /|\
	   / | \
	  /  |  \
	 /   |   \
	/    |    \
(pid_ns1) C1     C2    C3 (pid_ns1)
	 (pid_ns2)

where pid_ns1 is a parent of pid_ns2:

	   pid_ns1
	      |
	   pid_ns2

Children C1, C2 and C3 created in the written order,
i.e. C1 has the smallest pid and C2 has the biggest.

After receiving signal check, that pid namespaces
restored right.

Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
---
 test/zdtm/static/Makefile     |    1 
 test/zdtm/static/pidns00.c    |  206 +++++++++++++++++++++++++++++++++++++++++
 test/zdtm/static/pidns00.desc |    1 
 3 files changed, 208 insertions(+)
 create mode 100644 test/zdtm/static/pidns00.c
 create mode 100644 test/zdtm/static/pidns00.desc

Patch hide | download patch | download mbox

diff --git a/test/zdtm/static/Makefile b/test/zdtm/static/Makefile
index 8d5641bb..1c921d35 100644
--- a/test/zdtm/static/Makefile
+++ b/test/zdtm/static/Makefile
@@ -182,6 +182,7 @@  TST_NOFILE	:=				\
 		userns01			\
 		userns02			\
 		netns_sub_veth			\
+		pidns00				\
 #		jobctl00			\
 
 ifneq ($(SRCARCH),arm)
diff --git a/test/zdtm/static/pidns00.c b/test/zdtm/static/pidns00.c
new file mode 100644
index 00000000..cdfdbd3d
--- /dev/null
+++ b/test/zdtm/static/pidns00.c
@@ -0,0 +1,206 @@ 
+#define _GNU_SOURCE
+#include <stdbool.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <signal.h>
+#include <stdio.h>
+#include <sys/mount.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sched.h>
+#include <sys/wait.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <dirent.h>
+
+#include "zdtmtst.h"
+#include "lock.h"
+
+/*
+ * Create parent (P) and its three children (C1, C2 and C3)
+ * with different pid namespaces:
+ *
+ *                  P (pid_ns1)
+ *                 /|\
+ *                / | \
+ *               /  |  \
+ *              /   |   \
+ *             /    |    \
+ * (pid_ns1) C1     C2    C3 (pid_ns1)
+ *              (pid_ns2)
+ *
+ * where pid_ns1 is a parent of pid_ns2:
+ *
+ *               pid_ns1
+ *                  |
+ *               pid_ns2
+ * Children C1, C2 and C3 created in the written order,
+ * i.e. C1 has the smallest pid and C2 has the biggest
+ * (so, current restorer should restore them in the same order).
+ * After receiving signal check, that pid namespaces
+ * restored right.
+ */
+
+#ifndef NSIO
+#define NSIO    0xb7
+#define NS_GET_PARENT   _IO(NSIO, 0x2)
+#endif
+
+const char *test_doc	= "Check pid namespace hierarhy restores right";
+const char *test_author	= "Kirill Tkhai <ktkhai@virtuozzo.com>";
+
+futex_t *futex;
+
+int child(void)
+{
+	futex_wait_while_lt(futex, 1);
+	return 0;
+}
+
+int __get_ns_id(int fd, unsigned int *id)
+{
+	struct stat st;
+	if (fstat(fd, &st) < 0) {
+		pr_perror("fstat() kaput");
+		return 1;
+	}
+	*id = st.st_ino;
+	return 0;
+}
+
+int get_ns_id(pid_t pid, unsigned int *id)
+{
+	char buf[PATH_MAX];
+	int fd, ret;
+	sprintf(buf, "/proc/%d/ns/pid", pid);
+	fd = open(buf, O_RDONLY);
+	if (fd < 0) {
+		pr_perror("Can't open %s", buf);
+		return -1;
+	}
+	ret = __get_ns_id(fd, id);
+	close(fd);
+	return ret;
+}
+int main(int argc, char **argv)
+{
+	int status, fd, p_fd, i, nr = 0;
+	unsigned int id, c_id;
+	char path[PATH_MAX];
+	pid_t pid[3];
+
+	test_init(argc, argv);
+	futex = mmap(NULL, sizeof(*futex), PROT_WRITE | PROT_READ, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
+	if (futex == MAP_FAILED) {
+		fail("mmap futex\n");
+		return 1;
+	}
+	futex_init(futex);
+
+	/* Child 1 */
+	pid[0] = fork();
+	if (pid[0] == -1) {
+		fail("fork");
+		return 1;
+	} else if (pid[0] == 0)
+		exit(child());
+	nr++;
+
+	/* Child 2 */
+	fd = open("/proc/self/ns/pid", O_RDONLY);
+	if (fd < 0) {
+		pr_perror("Can't get my own pid ns");
+		goto err;
+	}
+
+	if (unshare(CLONE_NEWPID) < 0) {
+		pr_perror("Can't unshare");
+		goto err;
+	}
+
+	pid[1] = fork();
+	if (pid[1] == -1) {
+		fail("fork");
+		return 1;
+	} else if (pid[1] == 0)
+		exit(child());
+	nr++;
+
+	/* Restore pid namespace for children */
+	if (setns(fd, CLONE_NEWPID) < 0) {
+		pr_perror("Can't setns");
+		goto err;
+	}
+	close(fd);
+
+	/* Child 3 */
+	pid[2] = fork();
+	if (pid[2] == -1) {
+		fail("fork");
+		goto err;
+	} else if (pid[2] == 0)
+		exit(child());
+	nr++;
+
+	test_daemon();
+	test_waitsig();
+
+	if (get_ns_id(getpid(), &id))
+		goto err;
+
+	for (i = 0; i < nr; i++) {
+		if (get_ns_id(pid[i], &c_id))
+			goto err;
+		if (i % 2 == 0) {
+			if (c_id != id) {
+				pr_err("Child %d has wrong pid ns\n", i);
+				goto err;
+			}
+			continue;
+		}
+
+		if (id == c_id) {
+			pr_err("Child %d has wrong pid ns\n", i);
+			goto err;
+		}
+		/* This parent namespace of this Child's should be same to ours */
+		sprintf(path, "/proc/%d/ns/pid", pid[i]);
+		fd = open(path, O_RDONLY);
+		if (fd < 0) {
+			pr_perror("Can't open");
+			goto err;
+		}
+		p_fd = ioctl(fd, NS_GET_PARENT);
+		if (p_fd < 0)
+			pr_perror("Can't get parent");
+		close(fd);
+		if (p_fd < 0)
+			goto err;
+		if (__get_ns_id(p_fd, &c_id))
+			goto err;
+		close(p_fd);
+		if (id != c_id) {
+			pr_err("Child %d has wrong pid ns hierarhy\n", i);
+			goto err;
+		}
+	}
+
+	futex_set_and_wake(futex, 1);
+
+	while (nr-- > 0) {
+		if (wait(&status) < 0 || WEXITSTATUS(status)) {
+			fail("pid: status=%d\n", WEXITSTATUS(status));
+			goto err;
+		}
+	}
+
+	pass();
+	return 0;
+err:
+	futex_set_and_wake(futex, 1);
+	while (nr-- > 0)
+		wait(&status);
+	return 1;
+}
diff --git a/test/zdtm/static/pidns00.desc b/test/zdtm/static/pidns00.desc
new file mode 100644
index 00000000..41c1adcc
--- /dev/null
+++ b/test/zdtm/static/pidns00.desc
@@ -0,0 +1 @@ 
+{'flavor': 'ns uns', 'flags': 'suid noauto'}

Comments

Andrey Vagin April 5, 2017, 10:32 p.m.
@@ -55,6 +54,12 @@ futex_t *futex;
 
 int child(void)
 {
+       int fd;
+       fd = open("/proc/self/ns/pid", O_RDONLY);
+       unshare(CLONE_NEWPID);
+       fork();
+       setns(fd, CLONE_NEWPID);
+       close(fd);
        futex_wait_while_lt(futex, 1);
        return 0;
 }

[root@fc24 criu]# python test/zdtm.py run -t zdtm/static/pidns00 --iter 1 --sbs
=== Run 1/1 ================ zdtm/static/pidns00

======================== Run zdtm/static/pidns00 in ns =========================
make[1]: Nothing to be done for 'default'.
Start test
Test is SUID
make[1]: Nothing to be done for 'default'.
./pidns00 --pidfile=pidns00.pid --outfile=pidns00.out
Pause at pre-dump. Press any key to continue.
Run criu dump
Pause at pre-restore. Press any key to continue.
Run criu restore
=[log]=> dump/zdtm/static/pidns00/30/1/restore.log
------------------------ grep Error ------------------------
(00.021200) Add cgroup ns 7 pid 1
(00.021467) pstree pid_max=12
(00.021487) Will restore in 6c020000 namespaces
(00.021499) NS mask to use 6c020000
(00.021537) Error (criu/pstree.c:522): pid is already linked
------------------------ ERROR OVER ------------------------
################ Test zdtm/static/pidns00 FAIL at CRIU restore #################
##################################### FAIL #####################################

On Tue, Mar 28, 2017 at 06:35:24PM +0300, Kirill Tkhai wrote:
> Create parent (P) and its three children (C1, C2 and C3)
> with different pid namespaces:
> 
> 	     P (pid_ns1)
> 	    /|\
> 	   / | \
> 	  /  |  \
> 	 /   |   \
> 	/    |    \
> (pid_ns1) C1     C2    C3 (pid_ns1)
> 	 (pid_ns2)
> 
> where pid_ns1 is a parent of pid_ns2:
> 
> 	   pid_ns1
> 	      |
> 	   pid_ns2
> 
> Children C1, C2 and C3 created in the written order,
> i.e. C1 has the smallest pid and C2 has the biggest.
> 
> After receiving signal check, that pid namespaces
> restored right.
> 
> Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
> ---
>  test/zdtm/static/Makefile     |    1 
>  test/zdtm/static/pidns00.c    |  206 +++++++++++++++++++++++++++++++++++++++++
>  test/zdtm/static/pidns00.desc |    1 
>  3 files changed, 208 insertions(+)
>  create mode 100644 test/zdtm/static/pidns00.c
>  create mode 100644 test/zdtm/static/pidns00.desc
> 
> diff --git a/test/zdtm/static/Makefile b/test/zdtm/static/Makefile
> index 8d5641bb..1c921d35 100644
> --- a/test/zdtm/static/Makefile
> +++ b/test/zdtm/static/Makefile
> @@ -182,6 +182,7 @@ TST_NOFILE	:=				\
>  		userns01			\
>  		userns02			\
>  		netns_sub_veth			\
> +		pidns00				\
>  #		jobctl00			\
>  
>  ifneq ($(SRCARCH),arm)
> diff --git a/test/zdtm/static/pidns00.c b/test/zdtm/static/pidns00.c
> new file mode 100644
> index 00000000..cdfdbd3d
> --- /dev/null
> +++ b/test/zdtm/static/pidns00.c
> @@ -0,0 +1,206 @@
> +#define _GNU_SOURCE
> +#include <stdbool.h>
> +#include <string.h>
> +#include <fcntl.h>
> +#include <unistd.h>
> +#include <signal.h>
> +#include <stdio.h>
> +#include <sys/mount.h>
> +#include <sys/stat.h>
> +#include <sys/mman.h>
> +#include <sys/types.h>
> +#include <sched.h>
> +#include <sys/wait.h>
> +#include <stdlib.h>
> +#include <limits.h>
> +#include <dirent.h>
> +
> +#include "zdtmtst.h"
> +#include "lock.h"
> +
> +/*
> + * Create parent (P) and its three children (C1, C2 and C3)
> + * with different pid namespaces:
> + *
> + *                  P (pid_ns1)
> + *                 /|\
> + *                / | \
> + *               /  |  \
> + *              /   |   \
> + *             /    |    \
> + * (pid_ns1) C1     C2    C3 (pid_ns1)
> + *              (pid_ns2)
> + *
> + * where pid_ns1 is a parent of pid_ns2:
> + *
> + *               pid_ns1
> + *                  |
> + *               pid_ns2
> + * Children C1, C2 and C3 created in the written order,
> + * i.e. C1 has the smallest pid and C2 has the biggest
> + * (so, current restorer should restore them in the same order).
> + * After receiving signal check, that pid namespaces
> + * restored right.
> + */
> +
> +#ifndef NSIO
> +#define NSIO    0xb7
> +#define NS_GET_PARENT   _IO(NSIO, 0x2)
> +#endif
> +
> +const char *test_doc	= "Check pid namespace hierarhy restores right";
> +const char *test_author	= "Kirill Tkhai <ktkhai@virtuozzo.com>";
> +
> +futex_t *futex;
> +
> +int child(void)
> +{
> +	futex_wait_while_lt(futex, 1);
> +	return 0;
> +}
> +
> +int __get_ns_id(int fd, unsigned int *id)
> +{
> +	struct stat st;
> +	if (fstat(fd, &st) < 0) {
> +		pr_perror("fstat() kaput");
> +		return 1;
> +	}
> +	*id = st.st_ino;
> +	return 0;
> +}
> +
> +int get_ns_id(pid_t pid, unsigned int *id)
> +{
> +	char buf[PATH_MAX];
> +	int fd, ret;
> +	sprintf(buf, "/proc/%d/ns/pid", pid);
> +	fd = open(buf, O_RDONLY);
> +	if (fd < 0) {
> +		pr_perror("Can't open %s", buf);
> +		return -1;
> +	}
> +	ret = __get_ns_id(fd, id);
> +	close(fd);
> +	return ret;
> +}
> +int main(int argc, char **argv)
> +{
> +	int status, fd, p_fd, i, nr = 0;
> +	unsigned int id, c_id;
> +	char path[PATH_MAX];
> +	pid_t pid[3];
> +
> +	test_init(argc, argv);
> +	futex = mmap(NULL, sizeof(*futex), PROT_WRITE | PROT_READ, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
> +	if (futex == MAP_FAILED) {
> +		fail("mmap futex\n");
> +		return 1;
> +	}
> +	futex_init(futex);
> +
> +	/* Child 1 */
> +	pid[0] = fork();
> +	if (pid[0] == -1) {
> +		fail("fork");
> +		return 1;
> +	} else if (pid[0] == 0)
> +		exit(child());
> +	nr++;
> +
> +	/* Child 2 */
> +	fd = open("/proc/self/ns/pid", O_RDONLY);
> +	if (fd < 0) {
> +		pr_perror("Can't get my own pid ns");
> +		goto err;
> +	}
> +
> +	if (unshare(CLONE_NEWPID) < 0) {
> +		pr_perror("Can't unshare");
> +		goto err;
> +	}
> +
> +	pid[1] = fork();
> +	if (pid[1] == -1) {
> +		fail("fork");
> +		return 1;
> +	} else if (pid[1] == 0)
> +		exit(child());
> +	nr++;
> +
> +	/* Restore pid namespace for children */
> +	if (setns(fd, CLONE_NEWPID) < 0) {
> +		pr_perror("Can't setns");
> +		goto err;
> +	}
> +	close(fd);
> +
> +	/* Child 3 */
> +	pid[2] = fork();
> +	if (pid[2] == -1) {
> +		fail("fork");
> +		goto err;
> +	} else if (pid[2] == 0)
> +		exit(child());
> +	nr++;
> +
> +	test_daemon();
> +	test_waitsig();
> +
> +	if (get_ns_id(getpid(), &id))
> +		goto err;
> +
> +	for (i = 0; i < nr; i++) {
> +		if (get_ns_id(pid[i], &c_id))
> +			goto err;
> +		if (i % 2 == 0) {
> +			if (c_id != id) {
> +				pr_err("Child %d has wrong pid ns\n", i);
> +				goto err;
> +			}
> +			continue;
> +		}
> +
> +		if (id == c_id) {
> +			pr_err("Child %d has wrong pid ns\n", i);
> +			goto err;
> +		}
> +		/* This parent namespace of this Child's should be same to ours */
> +		sprintf(path, "/proc/%d/ns/pid", pid[i]);
> +		fd = open(path, O_RDONLY);
> +		if (fd < 0) {
> +			pr_perror("Can't open");
> +			goto err;
> +		}
> +		p_fd = ioctl(fd, NS_GET_PARENT);
> +		if (p_fd < 0)
> +			pr_perror("Can't get parent");
> +		close(fd);
> +		if (p_fd < 0)
> +			goto err;
> +		if (__get_ns_id(p_fd, &c_id))
> +			goto err;
> +		close(p_fd);
> +		if (id != c_id) {
> +			pr_err("Child %d has wrong pid ns hierarhy\n", i);
> +			goto err;
> +		}
> +	}
> +
> +	futex_set_and_wake(futex, 1);
> +
> +	while (nr-- > 0) {
> +		if (wait(&status) < 0 || WEXITSTATUS(status)) {
> +			fail("pid: status=%d\n", WEXITSTATUS(status));
> +			goto err;
> +		}
> +	}
> +
> +	pass();
> +	return 0;
> +err:
> +	futex_set_and_wake(futex, 1);
> +	while (nr-- > 0)
> +		wait(&status);
> +	return 1;
> +}
> diff --git a/test/zdtm/static/pidns00.desc b/test/zdtm/static/pidns00.desc
> new file mode 100644
> index 00000000..41c1adcc
> --- /dev/null
> +++ b/test/zdtm/static/pidns00.desc
> @@ -0,0 +1 @@
> +{'flavor': 'ns uns', 'flags': 'suid noauto'}
>
Kirill Tkhai April 6, 2017, 10:05 a.m.
On 06.04.2017 01:32, Andrei Vagin wrote:
> @@ -55,6 +54,12 @@ futex_t *futex;
>  
>  int child(void)
>  {
> +       int fd;
> +       fd = open("/proc/self/ns/pid", O_RDONLY);
> +       unshare(CLONE_NEWPID);
> +       fork();
> +       setns(fd, CLONE_NEWPID);
> +       close(fd);
>         futex_wait_while_lt(futex, 1);
>         return 0;
>  }
> 
> [root@fc24 criu]# python test/zdtm.py run -t zdtm/static/pidns00 --iter 1 --sbs
> === Run 1/1 ================ zdtm/static/pidns00
> 
> ======================== Run zdtm/static/pidns00 in ns =========================
> make[1]: Nothing to be done for 'default'.
> Start test
> Test is SUID
> make[1]: Nothing to be done for 'default'.
> ./pidns00 --pidfile=pidns00.pid --outfile=pidns00.out
> Pause at pre-dump. Press any key to continue.
> Run criu dump
> Pause at pre-restore. Press any key to continue.
> Run criu restore
> =[log]=> dump/zdtm/static/pidns00/30/1/restore.log
> ------------------------ grep Error ------------------------
> (00.021200) Add cgroup ns 7 pid 1
> (00.021467) pstree pid_max=12
> (00.021487) Will restore in 6c020000 namespaces
> (00.021499) NS mask to use 6c020000
> (00.021537) Error (criu/pstree.c:522): pid is already linked

Hm, can't reproduce so far.. Trying to find a reason

> ------------------------ ERROR OVER ------------------------
> ################ Test zdtm/static/pidns00 FAIL at CRIU restore #################
> ##################################### FAIL #####################################
> 
> On Tue, Mar 28, 2017 at 06:35:24PM +0300, Kirill Tkhai wrote:
>> Create parent (P) and its three children (C1, C2 and C3)
>> with different pid namespaces:
>>
>> 	     P (pid_ns1)
>> 	    /|\
>> 	   / | \
>> 	  /  |  \
>> 	 /   |   \
>> 	/    |    \
>> (pid_ns1) C1     C2    C3 (pid_ns1)
>> 	 (pid_ns2)
>>
>> where pid_ns1 is a parent of pid_ns2:
>>
>> 	   pid_ns1
>> 	      |
>> 	   pid_ns2
>>
>> Children C1, C2 and C3 created in the written order,
>> i.e. C1 has the smallest pid and C2 has the biggest.
>>
>> After receiving signal check, that pid namespaces
>> restored right.
>>
>> Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
>> ---
>>  test/zdtm/static/Makefile     |    1 
>>  test/zdtm/static/pidns00.c    |  206 +++++++++++++++++++++++++++++++++++++++++
>>  test/zdtm/static/pidns00.desc |    1 
>>  3 files changed, 208 insertions(+)
>>  create mode 100644 test/zdtm/static/pidns00.c
>>  create mode 100644 test/zdtm/static/pidns00.desc
>>
>> diff --git a/test/zdtm/static/Makefile b/test/zdtm/static/Makefile
>> index 8d5641bb..1c921d35 100644
>> --- a/test/zdtm/static/Makefile
>> +++ b/test/zdtm/static/Makefile
>> @@ -182,6 +182,7 @@ TST_NOFILE	:=				\
>>  		userns01			\
>>  		userns02			\
>>  		netns_sub_veth			\
>> +		pidns00				\
>>  #		jobctl00			\
>>  
>>  ifneq ($(SRCARCH),arm)
>> diff --git a/test/zdtm/static/pidns00.c b/test/zdtm/static/pidns00.c
>> new file mode 100644
>> index 00000000..cdfdbd3d
>> --- /dev/null
>> +++ b/test/zdtm/static/pidns00.c
>> @@ -0,0 +1,206 @@
>> +#define _GNU_SOURCE
>> +#include <stdbool.h>
>> +#include <string.h>
>> +#include <fcntl.h>
>> +#include <unistd.h>
>> +#include <signal.h>
>> +#include <stdio.h>
>> +#include <sys/mount.h>
>> +#include <sys/stat.h>
>> +#include <sys/mman.h>
>> +#include <sys/types.h>
>> +#include <sched.h>
>> +#include <sys/wait.h>
>> +#include <stdlib.h>
>> +#include <limits.h>
>> +#include <dirent.h>
>> +
>> +#include "zdtmtst.h"
>> +#include "lock.h"
>> +
>> +/*
>> + * Create parent (P) and its three children (C1, C2 and C3)
>> + * with different pid namespaces:
>> + *
>> + *                  P (pid_ns1)
>> + *                 /|\
>> + *                / | \
>> + *               /  |  \
>> + *              /   |   \
>> + *             /    |    \
>> + * (pid_ns1) C1     C2    C3 (pid_ns1)
>> + *              (pid_ns2)
>> + *
>> + * where pid_ns1 is a parent of pid_ns2:
>> + *
>> + *               pid_ns1
>> + *                  |
>> + *               pid_ns2
>> + * Children C1, C2 and C3 created in the written order,
>> + * i.e. C1 has the smallest pid and C2 has the biggest
>> + * (so, current restorer should restore them in the same order).
>> + * After receiving signal check, that pid namespaces
>> + * restored right.
>> + */
>> +
>> +#ifndef NSIO
>> +#define NSIO    0xb7
>> +#define NS_GET_PARENT   _IO(NSIO, 0x2)
>> +#endif
>> +
>> +const char *test_doc	= "Check pid namespace hierarhy restores right";
>> +const char *test_author	= "Kirill Tkhai <ktkhai@virtuozzo.com>";
>> +
>> +futex_t *futex;
>> +
>> +int child(void)
>> +{
>> +	futex_wait_while_lt(futex, 1);
>> +	return 0;
>> +}
>> +
>> +int __get_ns_id(int fd, unsigned int *id)
>> +{
>> +	struct stat st;
>> +	if (fstat(fd, &st) < 0) {
>> +		pr_perror("fstat() kaput");
>> +		return 1;
>> +	}
>> +	*id = st.st_ino;
>> +	return 0;
>> +}
>> +
>> +int get_ns_id(pid_t pid, unsigned int *id)
>> +{
>> +	char buf[PATH_MAX];
>> +	int fd, ret;
>> +	sprintf(buf, "/proc/%d/ns/pid", pid);
>> +	fd = open(buf, O_RDONLY);
>> +	if (fd < 0) {
>> +		pr_perror("Can't open %s", buf);
>> +		return -1;
>> +	}
>> +	ret = __get_ns_id(fd, id);
>> +	close(fd);
>> +	return ret;
>> +}
>> +int main(int argc, char **argv)
>> +{
>> +	int status, fd, p_fd, i, nr = 0;
>> +	unsigned int id, c_id;
>> +	char path[PATH_MAX];
>> +	pid_t pid[3];
>> +
>> +	test_init(argc, argv);
>> +	futex = mmap(NULL, sizeof(*futex), PROT_WRITE | PROT_READ, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
>> +	if (futex == MAP_FAILED) {
>> +		fail("mmap futex\n");
>> +		return 1;
>> +	}
>> +	futex_init(futex);
>> +
>> +	/* Child 1 */
>> +	pid[0] = fork();
>> +	if (pid[0] == -1) {
>> +		fail("fork");
>> +		return 1;
>> +	} else if (pid[0] == 0)
>> +		exit(child());
>> +	nr++;
>> +
>> +	/* Child 2 */
>> +	fd = open("/proc/self/ns/pid", O_RDONLY);
>> +	if (fd < 0) {
>> +		pr_perror("Can't get my own pid ns");
>> +		goto err;
>> +	}
>> +
>> +	if (unshare(CLONE_NEWPID) < 0) {
>> +		pr_perror("Can't unshare");
>> +		goto err;
>> +	}
>> +
>> +	pid[1] = fork();
>> +	if (pid[1] == -1) {
>> +		fail("fork");
>> +		return 1;
>> +	} else if (pid[1] == 0)
>> +		exit(child());
>> +	nr++;
>> +
>> +	/* Restore pid namespace for children */
>> +	if (setns(fd, CLONE_NEWPID) < 0) {
>> +		pr_perror("Can't setns");
>> +		goto err;
>> +	}
>> +	close(fd);
>> +
>> +	/* Child 3 */
>> +	pid[2] = fork();
>> +	if (pid[2] == -1) {
>> +		fail("fork");
>> +		goto err;
>> +	} else if (pid[2] == 0)
>> +		exit(child());
>> +	nr++;
>> +
>> +	test_daemon();
>> +	test_waitsig();
>> +
>> +	if (get_ns_id(getpid(), &id))
>> +		goto err;
>> +
>> +	for (i = 0; i < nr; i++) {
>> +		if (get_ns_id(pid[i], &c_id))
>> +			goto err;
>> +		if (i % 2 == 0) {
>> +			if (c_id != id) {
>> +				pr_err("Child %d has wrong pid ns\n", i);
>> +				goto err;
>> +			}
>> +			continue;
>> +		}
>> +
>> +		if (id == c_id) {
>> +			pr_err("Child %d has wrong pid ns\n", i);
>> +			goto err;
>> +		}
>> +		/* This parent namespace of this Child's should be same to ours */
>> +		sprintf(path, "/proc/%d/ns/pid", pid[i]);
>> +		fd = open(path, O_RDONLY);
>> +		if (fd < 0) {
>> +			pr_perror("Can't open");
>> +			goto err;
>> +		}
>> +		p_fd = ioctl(fd, NS_GET_PARENT);
>> +		if (p_fd < 0)
>> +			pr_perror("Can't get parent");
>> +		close(fd);
>> +		if (p_fd < 0)
>> +			goto err;
>> +		if (__get_ns_id(p_fd, &c_id))
>> +			goto err;
>> +		close(p_fd);
>> +		if (id != c_id) {
>> +			pr_err("Child %d has wrong pid ns hierarhy\n", i);
>> +			goto err;
>> +		}
>> +	}
>> +
>> +	futex_set_and_wake(futex, 1);
>> +
>> +	while (nr-- > 0) {
>> +		if (wait(&status) < 0 || WEXITSTATUS(status)) {
>> +			fail("pid: status=%d\n", WEXITSTATUS(status));
>> +			goto err;
>> +		}
>> +	}
>> +
>> +	pass();
>> +	return 0;
>> +err:
>> +	futex_set_and_wake(futex, 1);
>> +	while (nr-- > 0)
>> +		wait(&status);
>> +	return 1;
>> +}
>> diff --git a/test/zdtm/static/pidns00.desc b/test/zdtm/static/pidns00.desc
>> new file mode 100644
>> index 00000000..41c1adcc
>> --- /dev/null
>> +++ b/test/zdtm/static/pidns00.desc
>> @@ -0,0 +1 @@
>> +{'flavor': 'ns uns', 'flags': 'suid noauto'}
>>
Andrey Vagin April 7, 2017, 12:09 a.m.
On Thu, Apr 06, 2017 at 01:05:49PM +0300, Kirill Tkhai wrote:
> On 06.04.2017 01:32, Andrei Vagin wrote:
> > @@ -55,6 +54,12 @@ futex_t *futex;
> >  
> >  int child(void)
> >  {
> > +       int fd;
> > +       fd = open("/proc/self/ns/pid", O_RDONLY);
> > +       unshare(CLONE_NEWPID);
> > +       fork();
> > +       setns(fd, CLONE_NEWPID);
> > +       close(fd);
> >         futex_wait_while_lt(futex, 1);
> >         return 0;
> >  }
> > 
> > [root@fc24 criu]# python test/zdtm.py run -t zdtm/static/pidns00 --iter 1 --sbs
> > === Run 1/1 ================ zdtm/static/pidns00
> > 
> > ======================== Run zdtm/static/pidns00 in ns =========================
> > make[1]: Nothing to be done for 'default'.
> > Start test
> > Test is SUID
> > make[1]: Nothing to be done for 'default'.
> > ./pidns00 --pidfile=pidns00.pid --outfile=pidns00.out
> > Pause at pre-dump. Press any key to continue.
> > Run criu dump
> > Pause at pre-restore. Press any key to continue.
> > Run criu restore
> > =[log]=> dump/zdtm/static/pidns00/30/1/restore.log
> > ------------------------ grep Error ------------------------
> > (00.021200) Add cgroup ns 7 pid 1
> > (00.021467) pstree pid_max=12
> > (00.021487) Will restore in 6c020000 namespaces
> > (00.021499) NS mask to use 6c020000
> > (00.021537) Error (criu/pstree.c:522): pid is already linked
> 
> Hm, can't reproduce so far.. Trying to find a reason

Can you create a actual git repo with all these patches? Now they are
not applied and maybe I rebased them incorrectly...

> 
> > ------------------------ ERROR OVER ------------------------
> > ################ Test zdtm/static/pidns00 FAIL at CRIU restore #################
> > ##################################### FAIL #####################################
> > 
> > On Tue, Mar 28, 2017 at 06:35:24PM +0300, Kirill Tkhai wrote:
> >> Create parent (P) and its three children (C1, C2 and C3)
> >> with different pid namespaces:
> >>
> >> 	     P (pid_ns1)
> >> 	    /|\
> >> 	   / | \
> >> 	  /  |  \
> >> 	 /   |   \
> >> 	/    |    \
> >> (pid_ns1) C1     C2    C3 (pid_ns1)
> >> 	 (pid_ns2)
> >>
> >> where pid_ns1 is a parent of pid_ns2:
> >>
> >> 	   pid_ns1
> >> 	      |
> >> 	   pid_ns2
> >>
> >> Children C1, C2 and C3 created in the written order,
> >> i.e. C1 has the smallest pid and C2 has the biggest.
> >>
> >> After receiving signal check, that pid namespaces
> >> restored right.
> >>
> >> Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
> >> ---
> >>  test/zdtm/static/Makefile     |    1 
> >>  test/zdtm/static/pidns00.c    |  206 +++++++++++++++++++++++++++++++++++++++++
> >>  test/zdtm/static/pidns00.desc |    1 
> >>  3 files changed, 208 insertions(+)
> >>  create mode 100644 test/zdtm/static/pidns00.c
> >>  create mode 100644 test/zdtm/static/pidns00.desc
> >>
> >> diff --git a/test/zdtm/static/Makefile b/test/zdtm/static/Makefile
> >> index 8d5641bb..1c921d35 100644
> >> --- a/test/zdtm/static/Makefile
> >> +++ b/test/zdtm/static/Makefile
> >> @@ -182,6 +182,7 @@ TST_NOFILE	:=				\
> >>  		userns01			\
> >>  		userns02			\
> >>  		netns_sub_veth			\
> >> +		pidns00				\
> >>  #		jobctl00			\
> >>  
> >>  ifneq ($(SRCARCH),arm)
> >> diff --git a/test/zdtm/static/pidns00.c b/test/zdtm/static/pidns00.c
> >> new file mode 100644
> >> index 00000000..cdfdbd3d
> >> --- /dev/null
> >> +++ b/test/zdtm/static/pidns00.c
> >> @@ -0,0 +1,206 @@
> >> +#define _GNU_SOURCE
> >> +#include <stdbool.h>
> >> +#include <string.h>
> >> +#include <fcntl.h>
> >> +#include <unistd.h>
> >> +#include <signal.h>
> >> +#include <stdio.h>
> >> +#include <sys/mount.h>
> >> +#include <sys/stat.h>
> >> +#include <sys/mman.h>
> >> +#include <sys/types.h>
> >> +#include <sched.h>
> >> +#include <sys/wait.h>
> >> +#include <stdlib.h>
> >> +#include <limits.h>
> >> +#include <dirent.h>
> >> +
> >> +#include "zdtmtst.h"
> >> +#include "lock.h"
> >> +
> >> +/*
> >> + * Create parent (P) and its three children (C1, C2 and C3)
> >> + * with different pid namespaces:
> >> + *
> >> + *                  P (pid_ns1)
> >> + *                 /|\
> >> + *                / | \
> >> + *               /  |  \
> >> + *              /   |   \
> >> + *             /    |    \
> >> + * (pid_ns1) C1     C2    C3 (pid_ns1)
> >> + *              (pid_ns2)
> >> + *
> >> + * where pid_ns1 is a parent of pid_ns2:
> >> + *
> >> + *               pid_ns1
> >> + *                  |
> >> + *               pid_ns2
> >> + * Children C1, C2 and C3 created in the written order,
> >> + * i.e. C1 has the smallest pid and C2 has the biggest
> >> + * (so, current restorer should restore them in the same order).
> >> + * After receiving signal check, that pid namespaces
> >> + * restored right.
> >> + */
> >> +
> >> +#ifndef NSIO
> >> +#define NSIO    0xb7
> >> +#define NS_GET_PARENT   _IO(NSIO, 0x2)
> >> +#endif
> >> +
> >> +const char *test_doc	= "Check pid namespace hierarhy restores right";
> >> +const char *test_author	= "Kirill Tkhai <ktkhai@virtuozzo.com>";
> >> +
> >> +futex_t *futex;
> >> +
> >> +int child(void)
> >> +{
> >> +	futex_wait_while_lt(futex, 1);
> >> +	return 0;
> >> +}
> >> +
> >> +int __get_ns_id(int fd, unsigned int *id)
> >> +{
> >> +	struct stat st;
> >> +	if (fstat(fd, &st) < 0) {
> >> +		pr_perror("fstat() kaput");
> >> +		return 1;
> >> +	}
> >> +	*id = st.st_ino;
> >> +	return 0;
> >> +}
> >> +
> >> +int get_ns_id(pid_t pid, unsigned int *id)
> >> +{
> >> +	char buf[PATH_MAX];
> >> +	int fd, ret;
> >> +	sprintf(buf, "/proc/%d/ns/pid", pid);
> >> +	fd = open(buf, O_RDONLY);
> >> +	if (fd < 0) {
> >> +		pr_perror("Can't open %s", buf);
> >> +		return -1;
> >> +	}
> >> +	ret = __get_ns_id(fd, id);
> >> +	close(fd);
> >> +	return ret;
> >> +}
> >> +int main(int argc, char **argv)
> >> +{
> >> +	int status, fd, p_fd, i, nr = 0;
> >> +	unsigned int id, c_id;
> >> +	char path[PATH_MAX];
> >> +	pid_t pid[3];
> >> +
> >> +	test_init(argc, argv);
> >> +	futex = mmap(NULL, sizeof(*futex), PROT_WRITE | PROT_READ, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
> >> +	if (futex == MAP_FAILED) {
> >> +		fail("mmap futex\n");
> >> +		return 1;
> >> +	}
> >> +	futex_init(futex);
> >> +
> >> +	/* Child 1 */
> >> +	pid[0] = fork();
> >> +	if (pid[0] == -1) {
> >> +		fail("fork");
> >> +		return 1;
> >> +	} else if (pid[0] == 0)
> >> +		exit(child());
> >> +	nr++;
> >> +
> >> +	/* Child 2 */
> >> +	fd = open("/proc/self/ns/pid", O_RDONLY);
> >> +	if (fd < 0) {
> >> +		pr_perror("Can't get my own pid ns");
> >> +		goto err;
> >> +	}
> >> +
> >> +	if (unshare(CLONE_NEWPID) < 0) {
> >> +		pr_perror("Can't unshare");
> >> +		goto err;
> >> +	}
> >> +
> >> +	pid[1] = fork();
> >> +	if (pid[1] == -1) {
> >> +		fail("fork");
> >> +		return 1;
> >> +	} else if (pid[1] == 0)
> >> +		exit(child());
> >> +	nr++;
> >> +
> >> +	/* Restore pid namespace for children */
> >> +	if (setns(fd, CLONE_NEWPID) < 0) {
> >> +		pr_perror("Can't setns");
> >> +		goto err;
> >> +	}
> >> +	close(fd);
> >> +
> >> +	/* Child 3 */
> >> +	pid[2] = fork();
> >> +	if (pid[2] == -1) {
> >> +		fail("fork");
> >> +		goto err;
> >> +	} else if (pid[2] == 0)
> >> +		exit(child());
> >> +	nr++;
> >> +
> >> +	test_daemon();
> >> +	test_waitsig();
> >> +
> >> +	if (get_ns_id(getpid(), &id))
> >> +		goto err;
> >> +
> >> +	for (i = 0; i < nr; i++) {
> >> +		if (get_ns_id(pid[i], &c_id))
> >> +			goto err;
> >> +		if (i % 2 == 0) {
> >> +			if (c_id != id) {
> >> +				pr_err("Child %d has wrong pid ns\n", i);
> >> +				goto err;
> >> +			}
> >> +			continue;
> >> +		}
> >> +
> >> +		if (id == c_id) {
> >> +			pr_err("Child %d has wrong pid ns\n", i);
> >> +			goto err;
> >> +		}
> >> +		/* This parent namespace of this Child's should be same to ours */
> >> +		sprintf(path, "/proc/%d/ns/pid", pid[i]);
> >> +		fd = open(path, O_RDONLY);
> >> +		if (fd < 0) {
> >> +			pr_perror("Can't open");
> >> +			goto err;
> >> +		}
> >> +		p_fd = ioctl(fd, NS_GET_PARENT);
> >> +		if (p_fd < 0)
> >> +			pr_perror("Can't get parent");
> >> +		close(fd);
> >> +		if (p_fd < 0)
> >> +			goto err;
> >> +		if (__get_ns_id(p_fd, &c_id))
> >> +			goto err;
> >> +		close(p_fd);
> >> +		if (id != c_id) {
> >> +			pr_err("Child %d has wrong pid ns hierarhy\n", i);
> >> +			goto err;
> >> +		}
> >> +	}
> >> +
> >> +	futex_set_and_wake(futex, 1);
> >> +
> >> +	while (nr-- > 0) {
> >> +		if (wait(&status) < 0 || WEXITSTATUS(status)) {
> >> +			fail("pid: status=%d\n", WEXITSTATUS(status));
> >> +			goto err;
> >> +		}
> >> +	}
> >> +
> >> +	pass();
> >> +	return 0;
> >> +err:
> >> +	futex_set_and_wake(futex, 1);
> >> +	while (nr-- > 0)
> >> +		wait(&status);
> >> +	return 1;
> >> +}
> >> diff --git a/test/zdtm/static/pidns00.desc b/test/zdtm/static/pidns00.desc
> >> new file mode 100644
> >> index 00000000..41c1adcc
> >> --- /dev/null
> >> +++ b/test/zdtm/static/pidns00.desc
> >> @@ -0,0 +1 @@
> >> +{'flavor': 'ns uns', 'flags': 'suid noauto'}
> >>