parasite: handle errors while a transport socket is being created

Currently if socket() or connect() syscall-s failed, parasite cures itself,
but criu has not got any signals and waits on accept().

This patch adds a futex to synchronize parasite and criu. The server socket
is created with SOCK_NONBLOCK and waits on the futex when a parasite
connects to it, only then criu calls accept() and it returns immediately.

Reported-by: Yohei Kamitsukasa <uhoidx@gmail.com>
Cc: Yohei Kamitsukasa <uhoidx@gmail.com>
Signed-off-by: Andrew Vagin <avagin@virtuozzo.com>
Reviewed-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Acked-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
This commit is contained in:
Andrew Vagin 2016-07-28 21:41:00 +03:00 committed by Pavel Emelyanov
parent 7d95face06
commit 64e74fab05
4 changed files with 16 additions and 2 deletions

View file

@ -15,6 +15,7 @@
#include "image.h"
#include "util-pie.h"
#include "lock.h"
#include "images/vma.pb-c.h"
#include "images/tty.pb-c.h"
@ -72,6 +73,7 @@ struct parasite_init_args {
struct rt_sigframe *sigframe;
void *sigreturn_addr;
futex_t daemon_connected;
};
struct parasite_unmap_args {

View file

@ -1678,7 +1678,7 @@ static int prep_ns_sockets(struct ns_id *ns, bool for_dump)
} else
ns->net.nlsk = -1;
ret = ns->net.seqsk = socket(PF_UNIX, SOCK_SEQPACKET, 0);
ret = ns->net.seqsk = socket(PF_UNIX, SOCK_SEQPACKET | SOCK_NONBLOCK, 0);
if (ret < 0) {
pr_perror("Can't create seqsk for parasite");
goto err_sq;

View file

@ -509,6 +509,8 @@ static int parasite_init_daemon(struct parasite_ctl *ctl, struct ns_id *net)
args->sigframe = ctl->rsigframe;
args->log_level = log_get_loglevel();
futex_set(&args->daemon_connected, 0);
if (prepare_tsock(ctl, pid, args, net))
goto err;
@ -520,6 +522,13 @@ static int parasite_init_daemon(struct parasite_ctl *ctl, struct ns_id *net)
if (parasite_run(pid, PTRACE_CONT, ctl->parasite_ip, ctl->rstack, &regs, &ctl->orig))
goto err;
futex_wait_while_eq(&args->daemon_connected, 0);
if (futex_get(&args->daemon_connected) != 1) {
errno = -(int)futex_get(&args->daemon_connected);
pr_perror("Unable to connect a transport socket");
goto err;
}
if (accept_tsock(ctl) < 0)
goto err;

View file

@ -735,7 +735,7 @@ static noinline __used int parasite_init_daemon(void *data)
args->sigreturn_addr = fini_sigreturn;
sigframe = args->sigframe;
tsock = sys_socket(PF_UNIX, SOCK_SEQPACKET, 0);
ret = tsock = sys_socket(PF_UNIX, SOCK_SEQPACKET, 0);
if (tsock < 0) {
pr_err("Can't create socket: %d\n", tsock);
goto err;
@ -747,6 +747,8 @@ static noinline __used int parasite_init_daemon(void *data)
goto err;
}
futex_set_and_wake(&args->daemon_connected, 1);
ret = recv_fd(tsock);
if (ret >= 0) {
log_set_fd(ret);
@ -758,6 +760,7 @@ static noinline __used int parasite_init_daemon(void *data)
parasite_daemon(data);
err:
futex_set_and_wake(&args->daemon_connected, ret);
fini();
BUG();