mirror of
https://github.com/checkpoint-restore/criu.git
synced 2026-07-19 01:26:22 +00:00
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: Stanislav Kinsbursky <skinsbursky@parallels.com> Signed-off-by: Andrey Vagin <avagin@openvz.org> Signed-off-by: Pavel Emelyanov <xemul@parallels.com>
This commit is contained in:
parent
c4148d7907
commit
e1b02a48c1
2 changed files with 25 additions and 30 deletions
28
mount.c
28
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;
|
||||
|
|
|
|||
27
namespaces.c
27
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)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue