[CRIU] [PATCH 8/8] parasite: use only one command for executing parasite in a daemon mode
Andrey Vagin
avagin at openvz.org
Thu Jul 11 05:46:55 EDT 2013
If a kernel supports PTRACE_SETSIGMASK, criu don't need to execute
PARASITE_CMD_INIT and PARASITE_CMD_DAEMONIZE, because the frist command
is used only for blocking signals. If criu crashes between these
commands, a process state will be corrupted, because all signals remain
blocked.
Signed-off-by: Andrey Vagin <avagin at openvz.org>
---
include/parasite.h | 10 +----
parasite-syscall.c | 128 ++++++++++++++++++-----------------------------------
pie/parasite.c | 91 ++++++++++++++++---------------------
3 files changed, 85 insertions(+), 144 deletions(-)
diff --git a/include/parasite.h b/include/parasite.h
index 68c7161..db11f75 100644
--- a/include/parasite.h
+++ b/include/parasite.h
@@ -23,16 +23,14 @@ enum {
PARASITE_CMD_IDLE = 0,
PARASITE_CMD_ACK,
- PARASITE_CMD_INIT,
+ PARASITE_CMD_INIT_DAEMON,
PARASITE_CMD_DUMP_THREAD,
/*
* These two must be greater than INITs.
*/
- PARASITE_CMD_DAEMONIZE,
PARASITE_CMD_DAEMONIZED,
- PARASITE_CMD_CFG_LOG,
PARASITE_CMD_FINI,
PARASITE_CMD_MPROTECT_VMAS,
@@ -67,15 +65,11 @@ struct parasite_init_args {
int h_addr_len;
struct sockaddr_un h_addr;
- k_rtsigset_t sig_blocked;
+ int log_level;
struct rt_sigframe *sigframe;
};
-struct parasite_log_args {
- int log_level;
-};
-
struct parasite_vma_entry
{
unsigned long start;
diff --git a/parasite-syscall.c b/parasite-syscall.c
index 4533f14..481b34f 100644
--- a/parasite-syscall.c
+++ b/parasite-syscall.c
@@ -202,13 +202,6 @@ static int parasite_execute_trap_by_pid(unsigned int cmd,
return ret;
}
-static int parasite_execute_trap(unsigned int cmd, struct parasite_ctl *ctl)
-{
- return parasite_execute_trap_by_pid(cmd, ctl, ctl->pid.real,
- &ctl->regs_orig, ctl->rstack,
- &ctl->sig_blocked);
-}
-
static int __parasite_send_cmd(int sockfd, struct ctl_msg *m)
{
int ret;
@@ -328,25 +321,6 @@ int parasite_send_fd(struct parasite_ctl *ctl, int fd)
return 0;
}
-static int parasite_set_logfd(struct parasite_ctl *ctl, pid_t pid)
-{
- int ret;
- struct parasite_log_args *a;
-
- ret = parasite_send_fd(ctl, log_get_fd());
- if (ret)
- return ret;
-
- a = parasite_args(ctl, struct parasite_log_args);
- a->log_level = log_get_loglevel();
-
- ret = parasite_execute_trap(PARASITE_CMD_CFG_LOG, ctl);
- if (ret < 0)
- return ret;
-
- return 0;
-}
-
static int ssock = -1;
static int prepare_tsock(struct parasite_ctl *ctl, pid_t pid,
@@ -404,35 +378,9 @@ static int accept_tsock()
return sock;
}
-static int parasite_init(struct parasite_ctl *ctl, pid_t pid, struct pstree_item *item)
+static int parasite_init_daemon(struct parasite_ctl *ctl)
{
struct parasite_init_args *args;
- int sock;
-
- args = parasite_args(ctl, struct parasite_init_args);
-
- args->sigframe = ctl->rsigframe;
-
- if (prepare_tsock(ctl, pid, args))
- goto err;
-
- if (parasite_execute_trap(PARASITE_CMD_INIT, ctl) < 0) {
- pr_err("Can't init parasite\n");
- goto err;
- }
-
- sock = accept_tsock();
- if (sock < 0)
- goto err;
-
- ctl->tsock = sock;
- return 0;
-err:
- return -1;
-}
-
-static int parasite_daemonize(struct parasite_ctl *ctl)
-{
pid_t pid = ctl->pid.real;
user_regs_struct_t regs;
struct ctl_msg m = { };
@@ -440,7 +388,15 @@ static int parasite_daemonize(struct parasite_ctl *ctl)
ksigfillset(&blockall);
- *ctl->addr_cmd = PARASITE_CMD_DAEMONIZE;
+ *ctl->addr_cmd = PARASITE_CMD_INIT_DAEMON;
+
+ args = parasite_args(ctl, struct parasite_init_args);
+
+ args->sigframe = ctl->rsigframe;
+ args->log_level = log_get_loglevel();
+
+ if (prepare_tsock(ctl, pid, args))
+ goto err;;
regs = ctl->regs_orig;
parasite_setup_regs(ctl->parasite_ip, ctl->rstack, ®s);
@@ -452,18 +408,24 @@ static int parasite_daemonize(struct parasite_ctl *ctl)
if (ptrace(PTRACE_SETSIGMASK, pid, sizeof(k_rtsigset_t), &blockall)) {
pr_perror("Can't block signals");
- goto err;
+ goto err_regs;
}
if (ptrace(PTRACE_CONT, pid, NULL, NULL)) {
pr_perror("Can't continue (pid: %d)\n", pid);
- ptrace(PTRACE_SETREGS, pid, NULL, ctl->regs_orig);
- goto err;
+ goto err_mask;
}
+ ctl->tsock = accept_tsock();
+ if (ctl->tsock < 0)
+ goto err;
+
+ if (parasite_send_fd(ctl, log_get_fd()))
+ goto err;
+
pr_info("Wait for parasite being daemonized...\n");
- if (parasite_wait_ack(ctl->tsock, PARASITE_CMD_DAEMONIZE, &m)) {
+ if (parasite_wait_ack(ctl->tsock, PARASITE_CMD_INIT_DAEMON, &m)) {
pr_err("Can't switch parasite %d to daemon mode %d\n",
pid, m.err);
goto err;
@@ -473,10 +435,12 @@ static int parasite_daemonize(struct parasite_ctl *ctl)
pr_info("Parasite %d has been switched to daemon mode\n", pid);
return 0;
+err_mask:
+ ptrace(PTRACE_SETSIGMASK, pid, sizeof(k_rtsigset_t),
+ &RT_SIGFRAME_UC(ctl->sigframe).uc_sigmask);
+err_regs:
+ ptrace(PTRACE_SETREGS, pid, NULL, ctl->regs_orig);
err:
- if (ptrace(PTRACE_SETSIGMASK, pid, sizeof(k_rtsigset_t), ctl->sig_blocked))
- pr_perror("Can't block signals");
-
return -1;
}
@@ -1000,6 +964,24 @@ static unsigned long parasite_args_size(struct vm_area_list *vmas, struct parasi
return round_up(size, PAGE_SIZE);
}
+static int parasite_start_daemon(struct parasite_ctl *ctl, struct pstree_item *item)
+{
+ pid_t pid = ctl->pid.real;
+
+ if (get_task_regs(pid, ctl->regs_orig, item->core[0])) {
+ pr_err("Can't obtain regs for thread %d\n", pid);
+ return -1;
+ }
+
+ if (construct_sigframe(ctl->sigframe, ctl->rsigframe, item->core[0]))
+ return -1;
+
+ if (parasite_init_daemon(ctl))
+ return -1;;
+
+ return 0;
+}
+
struct parasite_ctl *parasite_infect_seized(pid_t pid, struct pstree_item *item,
struct vm_area_list *vma_area_list, struct parasite_drain_fd *dfds,
int timer_n)
@@ -1059,28 +1041,7 @@ struct parasite_ctl *parasite_infect_seized(pid_t pid, struct pstree_item *item,
p += PARASITE_STACK_SIZE;
}
- ret = parasite_init(ctl, pid, item);
- if (ret) {
- pr_err("%d: Can't create a transport socket\n", pid);
- goto err_restore;
- }
-
- ret = get_task_regs(pid, ctl->regs_orig, item->core[0]);
- if (ret) {
- pr_err("Can't obtain regs for thread %d\n", pid);
- goto err_restore;
- }
-
- ret = parasite_set_logfd(ctl, pid);
- if (ret) {
- pr_err("%d: Can't set a logging descriptor\n", pid);
- goto err_restore;
- }
-
- if (construct_sigframe(ctl->sigframe, ctl->rsigframe, item->core[0]))
- goto err_restore;
-
- if (parasite_daemonize(ctl))
+ if (parasite_start_daemon(ctl, item))
goto err_restore;
return ctl;
@@ -1089,4 +1050,3 @@ err_restore:
parasite_cure_seized(ctl);
return NULL;
}
-
diff --git a/pie/parasite.c b/pie/parasite.c
index 4ceeb3e..c506e66 100644
--- a/pie/parasite.c
+++ b/pie/parasite.c
@@ -220,37 +220,6 @@ static int dump_thread(struct parasite_dump_thread *args)
return ret;
}
-static int init(struct parasite_init_args *args)
-{
- k_rtsigset_t to_block;
- int ret;
-
- sigframe = args->sigframe;
-
- ksigfillset(&to_block);
- ret = sys_sigprocmask(SIG_SETMASK, &to_block,
- &args->sig_blocked,
- sizeof(k_rtsigset_t));
- if (ret)
- return -1;
-
- tsock = sys_socket(PF_UNIX, SOCK_STREAM, 0);
- if (tsock < 0) {
- ret = tsock;
- goto err;
- }
-
- ret = sys_connect(tsock, (struct sockaddr *)&args->h_addr, args->h_addr_len);
- if (ret < 0)
- goto err;
-
- return 0;
-err:
- sys_sigprocmask(SIG_SETMASK, &args->sig_blocked,
- NULL, sizeof(k_rtsigset_t));
- return ret;
-}
-
static char proc_mountpoint[] = "proc.crtools";
static int parasite_get_proc_fd()
{
@@ -369,20 +338,6 @@ err:
return 0;
}
-static int parasite_cfg_log(struct parasite_log_args *args)
-{
- int ret;
-
- ret = recv_fd(tsock);
- if (ret >= 0) {
- log_set_fd(ret);
- log_set_loglevel(args->log_level);
- ret = 0;
- }
-
- return ret;
-}
-
static int parasite_check_vdso_mark(struct parasite_vdso_vma_entry *args)
{
struct vdso_mark *m = (void *)args->start;
@@ -471,7 +426,7 @@ static noinline __used int noinline parasite_daemon(void *args)
pr_debug("Running daemon thread leader\n");
/* Reply we're alive */
- if (__parasite_daemon_reply_ack(PARASITE_CMD_DAEMONIZE, 0))
+ if (__parasite_daemon_reply_ack(PARASITE_CMD_INIT_DAEMON, 0))
goto out;
ret = 0;
@@ -542,19 +497,51 @@ out:
return 0;
}
+static noinline __used int parasite_init_daemon(void *data)
+{
+ struct parasite_init_args *args = data;
+ int ret;
+
+ sigframe = args->sigframe;
+
+ tsock = sys_socket(PF_UNIX, SOCK_STREAM, 0);
+ if (tsock < 0) {
+ pr_err("Can't create socket: %d\n", tsock);
+ goto err;
+ }
+
+ ret = sys_connect(tsock, (struct sockaddr *)&args->h_addr, args->h_addr_len);
+ if (ret < 0) {
+ pr_err("Can't connect the control socket\n");
+ goto err;
+ }
+
+ ret = recv_fd(tsock);
+ if (ret >= 0) {
+ log_set_fd(ret);
+ log_set_loglevel(args->log_level);
+ ret = 0;
+ } else
+ goto err;
+
+ parasite_daemon(data);
+
+err:
+ fini();
+ BUG();
+
+ return -1;
+}
+
int __used parasite_service(unsigned int cmd, void *args)
{
pr_info("Parasite cmd %d/%x process\n", cmd, cmd);
switch (cmd) {
- case PARASITE_CMD_INIT:
- return init(args);
case PARASITE_CMD_DUMP_THREAD:
return dump_thread(args);
- case PARASITE_CMD_CFG_LOG:
- return parasite_cfg_log(args);
- case PARASITE_CMD_DAEMONIZE:
- return parasite_daemon(args);
+ case PARASITE_CMD_INIT_DAEMON:
+ return parasite_init_daemon(args);
}
pr_err("Unknown command to parasite: %d\n", cmd);
--
1.8.3.1
More information about the CRIU
mailing list