Commit 64e74fab authored by Andrew Vagin's avatar Andrew Vagin Committed by Pavel Emelyanov

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: 's avatarYohei Kamitsukasa <uhoidx@gmail.com>
Cc: Yohei Kamitsukasa <uhoidx@gmail.com>
Signed-off-by: 's avatarAndrew Vagin <avagin@virtuozzo.com>
Reviewed-by: 's avatarDmitry Safonov <dsafonov@virtuozzo.com>
Acked-by: 's avatarCyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: 's avatarPavel Emelyanov <xemul@virtuozzo.com>
parent 7d95face
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include "image.h" #include "image.h"
#include "util-pie.h" #include "util-pie.h"
#include "lock.h"
#include "images/vma.pb-c.h" #include "images/vma.pb-c.h"
#include "images/tty.pb-c.h" #include "images/tty.pb-c.h"
...@@ -72,6 +73,7 @@ struct parasite_init_args { ...@@ -72,6 +73,7 @@ struct parasite_init_args {
struct rt_sigframe *sigframe; struct rt_sigframe *sigframe;
void *sigreturn_addr; void *sigreturn_addr;
futex_t daemon_connected;
}; };
struct parasite_unmap_args { struct parasite_unmap_args {
......
...@@ -1678,7 +1678,7 @@ static int prep_ns_sockets(struct ns_id *ns, bool for_dump) ...@@ -1678,7 +1678,7 @@ static int prep_ns_sockets(struct ns_id *ns, bool for_dump)
} else } else
ns->net.nlsk = -1; 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) { if (ret < 0) {
pr_perror("Can't create seqsk for parasite"); pr_perror("Can't create seqsk for parasite");
goto err_sq; goto err_sq;
......
...@@ -509,6 +509,8 @@ static int parasite_init_daemon(struct parasite_ctl *ctl, struct ns_id *net) ...@@ -509,6 +509,8 @@ static int parasite_init_daemon(struct parasite_ctl *ctl, struct ns_id *net)
args->sigframe = ctl->rsigframe; args->sigframe = ctl->rsigframe;
args->log_level = log_get_loglevel(); args->log_level = log_get_loglevel();
futex_set(&args->daemon_connected, 0);
if (prepare_tsock(ctl, pid, args, net)) if (prepare_tsock(ctl, pid, args, net))
goto err; goto err;
...@@ -520,6 +522,13 @@ static int parasite_init_daemon(struct parasite_ctl *ctl, struct ns_id *net) ...@@ -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)) if (parasite_run(pid, PTRACE_CONT, ctl->parasite_ip, ctl->rstack, &regs, &ctl->orig))
goto err; 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) if (accept_tsock(ctl) < 0)
goto err; goto err;
......
...@@ -735,7 +735,7 @@ static noinline __used int parasite_init_daemon(void *data) ...@@ -735,7 +735,7 @@ static noinline __used int parasite_init_daemon(void *data)
args->sigreturn_addr = fini_sigreturn; args->sigreturn_addr = fini_sigreturn;
sigframe = args->sigframe; sigframe = args->sigframe;
tsock = sys_socket(PF_UNIX, SOCK_SEQPACKET, 0); ret = tsock = sys_socket(PF_UNIX, SOCK_SEQPACKET, 0);
if (tsock < 0) { if (tsock < 0) {
pr_err("Can't create socket: %d\n", tsock); pr_err("Can't create socket: %d\n", tsock);
goto err; goto err;
...@@ -747,6 +747,8 @@ static noinline __used int parasite_init_daemon(void *data) ...@@ -747,6 +747,8 @@ static noinline __used int parasite_init_daemon(void *data)
goto err; goto err;
} }
futex_set_and_wake(&args->daemon_connected, 1);
ret = recv_fd(tsock); ret = recv_fd(tsock);
if (ret >= 0) { if (ret >= 0) {
log_set_fd(ret); log_set_fd(ret);
...@@ -758,6 +760,7 @@ static noinline __used int parasite_init_daemon(void *data) ...@@ -758,6 +760,7 @@ static noinline __used int parasite_init_daemon(void *data)
parasite_daemon(data); parasite_daemon(data);
err: err:
futex_set_and_wake(&args->daemon_connected, ret);
fini(); fini();
BUG(); BUG();
......
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