[CRIU] [PATCH] zdtm: Add pidns02 test
Kirill Tkhai
ktkhai at virtuozzo.com
Wed May 10 05:38:14 PDT 2017
1)Create a pid namespace and child reaper in it;
2)Set a specific next pid for future created process;
3)Create one more process in the namespace and kill it;
4)Wait for signal
5)Check, that NSpids of dead task remains the same.
(Note, that currently we do not sort children to have
a specific order of their creation, and child reaper
is the second in the children list, so the test fails.
If you want to try it, replace restore_before_setsid()
in create_children_and_session() on
last_level_pid(child->pid) == 1 to have a order).
Signed-off-by: Kirill Tkhai <ktkhai at virtuozzo.com>
---
test/zdtm/static/Makefile | 1
test/zdtm/static/pidns02.c | 179 +++++++++++++++++++++++++++++++++++++++++
test/zdtm/static/pidns02.desc | 1
3 files changed, 181 insertions(+)
create mode 100644 test/zdtm/static/pidns02.c
create mode 100644 test/zdtm/static/pidns02.desc
diff --git a/test/zdtm/static/Makefile b/test/zdtm/static/Makefile
index 1ea9393ce..178e564d7 100644
--- a/test/zdtm/static/Makefile
+++ b/test/zdtm/static/Makefile
@@ -178,6 +178,7 @@ TST_NOFILE := \
netns_sub_veth \
pidns00 \
pidns01 \
+ pidns02 \
# jobctl00 \
ifneq ($(SRCARCH),arm)
diff --git a/test/zdtm/static/pidns02.c b/test/zdtm/static/pidns02.c
new file mode 100644
index 000000000..50277122d
--- /dev/null
+++ b/test/zdtm/static/pidns02.c
@@ -0,0 +1,179 @@
+#include <stdbool.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <signal.h>
+#include <stdio.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"
+
+const char *test_doc = "Check NSpids of dead tasks restore right";
+const char *test_author = "Kirill Tkhai <ktkhai at virtuozzo.com>";
+
+enum {
+ FUTEX_INITIALIZED = 0,
+ CHILD_PREPARED,
+ EMERGENCY_ABORT,
+};
+
+futex_t *futex;
+
+#define CHILD_NS_PID 11235
+#define PARENT_NS_PID 31415
+
+static int set_ns_next_pid(pid_t pid)
+{
+ char buf[32];
+ int len, fd;
+
+ fd = open("/proc/sys/kernel/ns_last_pid", O_WRONLY);
+ if (fd < 0)
+ return -1;
+
+ len = snprintf(buf, sizeof(buf), "%d", pid - 1);
+ len -= write(fd, buf, len);
+ if (len)
+ pr_perror("Can't set ns_last_pid");
+ close(fd);
+
+ return len ? -1 : 0;
+}
+
+static int sleep_loop(void)
+{
+ while (1)
+ sleep(60);
+ return 0;
+}
+
+static int child(void)
+{
+ if (set_ns_next_pid(CHILD_NS_PID)) {
+ futex_set_and_wake(futex, EMERGENCY_ABORT);
+ exit(1);
+ }
+
+ futex_set_and_wake(futex, CHILD_PREPARED);
+ return sleep_loop();
+}
+
+static int get_ns_pid(pid_t pid, char **str)
+{
+ char buf[64];
+ FILE *fp;
+ size_t n;
+
+ snprintf(buf, sizeof(buf), "/proc/%d/status", pid);
+ fp = fopen(buf, "r");
+ if (!fp) {
+ pr_perror("Can't open %s", buf);
+ return -1;
+ }
+
+ *str = NULL;
+ while (getline(str, &n, fp) != -1) {
+ if (strncmp(*str, "NSpid:", 6) == 0) {
+ fclose(fp);
+ return 0;
+ }
+ }
+
+ pr_err("NSpid has not found\n");
+ fclose(fp);
+ return -1;
+}
+/*
+ * 1)Create a pid namespace and child reaper in it;
+ * 2)Set a specific next pid for future created process;
+ * 3)Create one more process in the namespace and kill it;
+ * 4)Wait for signal
+ * 5)Check, that NSpids of dead task remains the same.
+ */
+int main(int argc, char **argv)
+{
+ int i, status, ret = -1;
+ pid_t pid[] = {-1, -1};
+ char *ns_pid, *tmp;
+
+ 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);
+
+ if (unshare(CLONE_NEWPID) < 0) {
+ fail("Can't unshare");
+ return 1;
+ }
+
+ /* Create child 1, child reaper of the new namespace */
+ pid[0] = fork();
+ if (pid[0] < 0) {
+ fail("Can't fork");
+ return 1;
+ } else if (pid[0] == 0)
+ exit(child());
+
+ futex_wait_while_lt(futex, CHILD_PREPARED);
+ if (futex_get(futex) == EMERGENCY_ABORT) {
+ pr_err("Fail during prepare of child 1\n");
+ goto out;
+ }
+
+ if (set_ns_next_pid(PARENT_NS_PID)) {
+ pr_err("Fail during next pid write\n");
+ goto out;
+ }
+
+ /* Child 2 is in the same namespace as child 1 */
+ pid[1] = fork();
+ if (pid[1] < 0) {
+ pr_perror("Can't fork");
+ goto out;
+ } else if (pid[1] == 0)
+ exit(sleep_loop());
+
+ if (get_ns_pid(pid[1], &ns_pid) < 0) {
+ pr_perror("Can't get ns_pid");
+ goto out;
+ }
+
+ if (kill(pid[1], SIGKILL))
+ pr_perror("Can't kill");
+
+ test_daemon();
+ test_waitsig();
+
+ if (get_ns_pid(pid[1], &tmp) < 0) {
+ pr_perror("Can't fork");
+ goto out;
+ }
+
+ if (strcmp(ns_pid, tmp)) {
+ pr_err("NSpid mismatch: %s %s\n", ns_pid, tmp);
+ goto out;
+ }
+
+ ret = 0;
+out:
+ /* Wait child reaper last as it waits namespace processes itself */
+ for (i = 1; i >= 0; i--) {
+ kill(pid[i], SIGKILL);
+ waitpid(pid[i], &status, 0);
+ }
+ if (ret)
+ fail("Test failed");
+ else
+ pass();
+ return ret;
+}
diff --git a/test/zdtm/static/pidns02.desc b/test/zdtm/static/pidns02.desc
new file mode 100644
index 000000000..d20a6722c
--- /dev/null
+++ b/test/zdtm/static/pidns02.desc
@@ -0,0 +1 @@
+{'flavor': 'uns', 'flags': 'suid noauto', 'feature': 'ns_pid'}
More information about the CRIU
mailing list