[CRIU] [PATCH cr] cr-restore: block SIGCHLD for restoring namespaces

Andrey Vagin avagin at openvz.org
Thu Sep 20 07:22:57 EDT 2012


Restore of namespaces requires executions of external tools
(ip, tar, etc). We want to know return codes, so we should
block a default sigchld handler. Before we did that for each
command, I suggest to block SIGCHLD, then restore namespace and
unblock SIGCHLD.

The default sigchld handler is used for catching target processes,
but all this processes (except a current one ) are started after
restoring namespaces.

Currently we forgot to block SIGCHLD before executing "ip",
and this bug was caught.

Reported-by: Stanislav Kinsbursky <skinsbursky at parallels.com>
Signed-off-by: Andrey Vagin <avagin at openvz.org>
---
 mount.c      |   28 +++-------------------------
 namespaces.c |   27 ++++++++++++++++++++++-----
 2 files changed, 25 insertions(+), 30 deletions(-)

diff --git a/mount.c b/mount.c
index 80992b8..4534ff3 100644
--- a/mount.c
+++ b/mount.c
@@ -309,26 +309,12 @@ static int tmpfs_dump(struct mount_info *pm)
 static int tmpfs_restore(struct mount_info *pm)
 {
 	int ret, status = -1;
-	sigset_t mask, oldmask;
 	pid_t pid;
 
-	ret = sigprocmask(SIG_SETMASK, NULL, &oldmask);
-	if (ret == -1) {
-		pr_perror("Can not get mask of blocked signals");
-		return -1;
-	}
-	mask = oldmask;
-	sigaddset(&mask, SIGCHLD);
-	ret = sigprocmask(SIG_SETMASK, &mask, NULL);
-	if (ret == -1) {
-		pr_perror("Can not set mask of blocked signals");
-		return -1;
-	}
-
 	pid = fork();
 	if (pid == -1) {
 		pr_perror("fork() failed\n");
-		goto out_unlock;
+		return -1;
 	} else if (pid == 0) {
 		int fd_img;
 
@@ -352,20 +338,12 @@ static int tmpfs_restore(struct mount_info *pm)
 	ret = waitpid(pid, &status, 0);
 	if (ret == -1) {
 		pr_perror("waitpid() failed");
-		goto out_unlock;
+		return -1;
 	}
 
 	if (status) {
 		pr_err("Can't restore tmpfs content\n");
-		status = -1;
-		goto out_unlock;
-	}
-
-out_unlock:
-	ret = sigprocmask(SIG_SETMASK, &oldmask, NULL);
-	if (ret == -1) {
-		pr_perror("Can not set mask of blocked signals");
-		BUG();
+		return -1;
 	}
 
 	return status;
diff --git a/namespaces.c b/namespaces.c
index dc8e008..55c0228 100644
--- a/namespaces.c
+++ b/namespaces.c
@@ -151,9 +151,19 @@ int dump_namespaces(struct pid *ns_pid, unsigned int ns_flags)
 
 int prepare_namespace(int pid, unsigned long clone_flags)
 {
+	sigset_t blockmask, oldmask;
+	int ret = -1;
+
 	pr_info("Restoring namespaces %d flags 0x%lx\n",
 			pid, clone_flags);
 
+	sigemptyset(&blockmask);
+	sigaddset(&blockmask, SIGCHLD);
+	if (sigprocmask(SIG_BLOCK, &blockmask, &oldmask) == -1) {
+		pr_perror("Can not set mask of blocked signals");
+		return -1;
+	}
+
 	/*
 	 * On netns restore we launch an IP tool, thus we
 	 * have to restore it _before_ altering the mount
@@ -161,15 +171,22 @@ int prepare_namespace(int pid, unsigned long clone_flags)
 	 */
 
 	if ((clone_flags & CLONE_NEWNET) && prepare_net_ns(pid))
-		return -1;
+		goto out;
 	if ((clone_flags & CLONE_NEWUTS) && prepare_utsns(pid))
-		return -1;
+		goto out;
 	if ((clone_flags & CLONE_NEWIPC) && prepare_ipc_ns(pid))
-		return -1;
+		goto out;
 	if ((clone_flags & CLONE_NEWNS)  && prepare_mnt_ns(pid))
-		return -1;
+		goto out;
 
-	return 0;
+	ret = 0;
+out:
+	if (sigprocmask(SIG_SETMASK, &oldmask, NULL) == -1) {
+		pr_perror("Can not set mask of blocked signals");
+		BUG();
+	}
+
+	return ret;
 }
 
 int try_show_namespaces(int ns_pid, struct cr_options *o)
-- 
1.7.1



More information about the CRIU mailing list