[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, &regs);
@@ -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