Commit e1b02a48 authored by Andrey Vagin's avatar Andrey Vagin Committed by Pavel Emelyanov

cr-restore: block SIGCHLD for restoring namespaces

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: 's avatarStanislav Kinsbursky <skinsbursky@parallels.com>
Signed-off-by: 's avatarAndrey Vagin <avagin@openvz.org>
Signed-off-by: 's avatarPavel Emelyanov <xemul@parallels.com>
parent c4148d79
...@@ -309,26 +309,12 @@ static int tmpfs_dump(struct mount_info *pm) ...@@ -309,26 +309,12 @@ static int tmpfs_dump(struct mount_info *pm)
static int tmpfs_restore(struct mount_info *pm) static int tmpfs_restore(struct mount_info *pm)
{ {
int ret, status = -1; int ret, status = -1;
sigset_t mask, oldmask;
pid_t pid; 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(); pid = fork();
if (pid == -1) { if (pid == -1) {
pr_perror("fork() failed\n"); pr_perror("fork() failed\n");
goto out_unlock; return -1;
} else if (pid == 0) { } else if (pid == 0) {
int fd_img; int fd_img;
...@@ -352,20 +338,12 @@ static int tmpfs_restore(struct mount_info *pm) ...@@ -352,20 +338,12 @@ static int tmpfs_restore(struct mount_info *pm)
ret = waitpid(pid, &status, 0); ret = waitpid(pid, &status, 0);
if (ret == -1) { if (ret == -1) {
pr_perror("waitpid() failed"); pr_perror("waitpid() failed");
goto out_unlock; return -1;
} }
if (status) { if (status) {
pr_err("Can't restore tmpfs content\n"); pr_err("Can't restore tmpfs content\n");
status = -1; return -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 status; return status;
......
...@@ -151,9 +151,19 @@ int dump_namespaces(struct pid *ns_pid, unsigned int ns_flags) ...@@ -151,9 +151,19 @@ int dump_namespaces(struct pid *ns_pid, unsigned int ns_flags)
int prepare_namespace(int pid, unsigned long clone_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", pr_info("Restoring namespaces %d flags 0x%lx\n",
pid, clone_flags); 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 * On netns restore we launch an IP tool, thus we
* have to restore it _before_ altering the mount * have to restore it _before_ altering the mount
...@@ -161,15 +171,22 @@ int prepare_namespace(int pid, unsigned long clone_flags) ...@@ -161,15 +171,22 @@ int prepare_namespace(int pid, unsigned long clone_flags)
*/ */
if ((clone_flags & CLONE_NEWNET) && prepare_net_ns(pid)) if ((clone_flags & CLONE_NEWNET) && prepare_net_ns(pid))
return -1; goto out;
if ((clone_flags & CLONE_NEWUTS) && prepare_utsns(pid)) if ((clone_flags & CLONE_NEWUTS) && prepare_utsns(pid))
return -1; goto out;
if ((clone_flags & CLONE_NEWIPC) && prepare_ipc_ns(pid)) if ((clone_flags & CLONE_NEWIPC) && prepare_ipc_ns(pid))
return -1; goto out;
if ((clone_flags & CLONE_NEWNS) && prepare_mnt_ns(pid)) 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) int try_show_namespaces(int ns_pid, struct cr_options *o)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment