[CRIU] [PATCH 69/78] pie: Detach infect

Cyrill Gorcunov gorcunov at openvz.org
Mon Nov 7 08:36:54 PST 2016


From: Pavel Emelyanov <xemul at virtuozzo.com>

This moves the previously splitted routines into pie/infect.c.

Signed-off-by: Pavel Emelyanov <xemul at virtuozzo.com>
---
 criu/arch/x86/include/asm/sigframe.h |   1 +
 criu/include/infect-pie.h            |   7 ++
 criu/pie/Makefile                    |   2 +
 criu/pie/compat/infect-compat.c      |   1 +
 criu/pie/infect.c                    | 220 +++++++++++++++++++++++++++++++++++
 criu/pie/parasite.c                  | 219 ++--------------------------------
 6 files changed, 242 insertions(+), 208 deletions(-)
 create mode 100644 criu/include/infect-pie.h
 create mode 120000 criu/pie/compat/infect-compat.c
 create mode 100644 criu/pie/infect.c

diff --git a/criu/arch/x86/include/asm/sigframe.h b/criu/arch/x86/include/asm/sigframe.h
index b86034bddf42..af2b67aca6a0 100644
--- a/criu/arch/x86/include/asm/sigframe.h
+++ b/criu/arch/x86/include/asm/sigframe.h
@@ -5,6 +5,7 @@
 #include <stdbool.h>
 
 #include <compel/asm/fpu.h>
+#include <compel/plugins/std/syscall-codes.h>
 
 #define SIGFRAME_MAX_OFFSET 8
 
diff --git a/criu/include/infect-pie.h b/criu/include/infect-pie.h
new file mode 100644
index 000000000000..b00d7dd2558d
--- /dev/null
+++ b/criu/include/infect-pie.h
@@ -0,0 +1,7 @@
+#ifndef __CR_INFECT_PIE_H__
+#define __CR_INFECT_PIE_H__
+extern int parasite_daemon_cmd(int cmd, void *args);
+extern int parasite_trap_cmd(int cmd, void *args);
+extern void parasite_cleanup(void);
+extern int parasite_get_rpc_sock(void);
+#endif
diff --git a/criu/pie/Makefile b/criu/pie/Makefile
index eb41415d944a..1b97e0726cee 100644
--- a/criu/pie/Makefile
+++ b/criu/pie/Makefile
@@ -7,7 +7,9 @@ ifeq ($(CONFIG_COMPAT),y)
 endif
 
 native-obj-y           += parasite.o
+native-obj-y           += infect.o
 compat-obj-y           += compat/parasite-compat.o
+compat-obj-y           += compat/infect-compat.o
 
 restorer-obj-y		+= restorer.o
 restorer-obj-y		+= ./$(ARCH_DIR)/restorer.o
diff --git a/criu/pie/compat/infect-compat.c b/criu/pie/compat/infect-compat.c
new file mode 120000
index 000000000000..87c7722b6548
--- /dev/null
+++ b/criu/pie/compat/infect-compat.c
@@ -0,0 +1 @@
+../infect.c
\ No newline at end of file
diff --git a/criu/pie/infect.c b/criu/pie/infect.c
new file mode 100644
index 000000000000..303b60b68ceb
--- /dev/null
+++ b/criu/pie/infect.c
@@ -0,0 +1,220 @@
+#include "common/compiler.h"
+#include "common/lock.h"
+#include "int.h"
+#include "util-pie.h"
+
+#include "criu-log.h"
+#include "common/bug.h"
+#include "sigframe.h"
+#include "infect-rpc.h"
+#include "infect-pie.h"
+
+static int tsock = -1;
+
+static struct rt_sigframe *sigframe;
+
+int parasite_get_rpc_sock(void)
+{
+	return tsock;
+}
+
+/* RPC helpers */
+static int __parasite_daemon_reply_ack(unsigned int cmd, int err)
+{
+	struct ctl_msg m;
+	int ret;
+
+	m = ctl_msg_ack(cmd, err);
+	ret = sys_sendto(tsock, &m, sizeof(m), 0, NULL, 0);
+	if (ret != sizeof(m)) {
+		pr_err("Sent only %d bytes while %zu expected\n", ret, sizeof(m));
+		return -1;
+	}
+
+	pr_debug("__sent ack msg: %d %d %d\n",
+		 m.cmd, m.ack, m.err);
+
+	return 0;
+}
+
+static int __parasite_daemon_wait_msg(struct ctl_msg *m)
+{
+	int ret;
+
+	pr_debug("Daemon waits for command\n");
+
+	while (1) {
+		*m = (struct ctl_msg){ };
+		ret = sys_recvfrom(tsock, m, sizeof(*m), MSG_WAITALL, NULL, 0);
+		if (ret != sizeof(*m)) {
+			pr_err("Trimmed message received (%d/%d)\n",
+			       (int)sizeof(*m), ret);
+			return -1;
+		}
+
+		pr_debug("__fetched msg: %d %d %d\n",
+			 m->cmd, m->ack, m->err);
+		return 0;
+	}
+
+	return -1;
+}
+
+/* Core infect code */
+
+static noinline void fini_sigreturn(unsigned long new_sp)
+{
+	ARCH_RT_SIGRETURN(new_sp, sigframe);
+}
+
+static int fini(void)
+{
+	unsigned long new_sp;
+
+	parasite_cleanup();
+
+	new_sp = (long)sigframe + RT_SIGFRAME_OFFSET(sigframe);
+	pr_debug("%ld: new_sp=%lx ip %lx\n", sys_gettid(),
+		  new_sp, RT_SIGFRAME_REGIP(sigframe));
+
+	sys_close(tsock);
+	log_set_fd(-1);
+
+	fini_sigreturn(new_sp);
+
+	BUG();
+
+	return -1;
+}
+
+static noinline __used int noinline parasite_daemon(void *args)
+{
+	struct ctl_msg m;
+	int ret = -1;
+
+	pr_debug("Running daemon thread leader\n");
+
+	/* Reply we're alive */
+	if (__parasite_daemon_reply_ack(PARASITE_CMD_INIT_DAEMON, 0))
+		goto out;
+
+	ret = 0;
+
+	while (1) {
+		if (__parasite_daemon_wait_msg(&m))
+			break;
+
+		if (ret && m.cmd != PARASITE_CMD_FINI) {
+			pr_err("Command rejected\n");
+			continue;
+		}
+
+		if (m.cmd == PARASITE_CMD_FINI)
+			goto out;
+
+		ret = parasite_daemon_cmd(m.cmd, args);
+
+		if (__parasite_daemon_reply_ack(m.cmd, ret))
+			break;
+
+		if (ret) {
+			pr_err("Close the control socket for writing\n");
+			sys_shutdown(tsock, SHUT_WR);
+		}
+	}
+
+out:
+	fini();
+
+	return 0;
+}
+
+static noinline int unmap_itself(void *data)
+{
+	struct parasite_unmap_args *args = data;
+
+	sys_munmap((void*)(uintptr_t)args->parasite_start, args->parasite_len);
+	/*
+	 * This call to sys_munmap must never return. Instead, the controlling
+	 * process must trap us on the exit from munmap.
+	 */
+
+	BUG();
+	return -1;
+}
+
+static noinline __used int parasite_init_daemon(void *data)
+{
+	struct parasite_init_args *args = data;
+	int ret;
+
+	args->sigreturn_addr = (uint64_t)(uintptr_t)fini_sigreturn;
+	sigframe = (void*)(uintptr_t)args->sigframe;
+
+	ret = tsock = sys_socket(PF_UNIX, SOCK_SEQPACKET, 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;
+	}
+
+	futex_set_and_wake(&args->daemon_connected, 1);
+
+	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:
+	futex_set_and_wake(&args->daemon_connected, ret);
+	fini();
+	BUG();
+
+	return -1;
+}
+
+#ifndef __parasite_entry
+# define __parasite_entry
+#endif
+
+int __used __parasite_entry parasite_service(unsigned int cmd, void *args)
+{
+	pr_info("Parasite cmd %d/%x process\n", cmd, cmd);
+
+	switch (cmd) {
+	case PARASITE_CMD_INIT_DAEMON:
+		return parasite_init_daemon(args);
+	case PARASITE_CMD_UNMAP:
+		return unmap_itself(args);
+	}
+
+	return parasite_trap_cmd(cmd, args);
+}
+
+/*
+ * Mainally, -fstack-protector is disabled for parasite.
+ * But we share some object files, compiled for CRIU with parasite.
+ * Those files (like cpu.c) may be compiled with stack protector
+ * support. We can't use gcc-ld provided stackprotector callback,
+ * as Glibc is unmapped. Let's just try to cure application in
+ * case of stack smashing in parasite.
+ */
+void __stack_chk_fail(void)
+{
+	/*
+	 * Smash didn't happen in printing part, as it's not shared
+	 * with CRIU, therefore compiled with -fnostack-protector.
+	 */
+	pr_err("Stack smash detected in parasite\n");
+	fini();
+}
diff --git a/criu/pie/parasite.c b/criu/pie/parasite.c
index 6d484a9d9375..5f5d13774ed2 100644
--- a/criu/pie/parasite.c
+++ b/criu/pie/parasite.c
@@ -19,19 +19,17 @@
 #include "tty.h"
 #include "aio.h"
 #include "infect-rpc.h"
+#include "infect-pie.h"
 
 #include "asm/parasite.h"
 #include "restorer.h"
+#include "infect-pie.h"
 
 int compel_main(void *arg_p, unsigned int arg_s)
 {
 	return 0;
 }
 
-static int tsock = -1;
-
-static struct rt_sigframe *sigframe;
-
 /*
  * PARASITE_CMD_DUMPPAGES is called many times and the parasite args contains
  * an array of VMAs at this time, so VMAs can be unprotected in any moment
@@ -74,9 +72,10 @@ static int mprotect_vmas(struct parasite_dump_pages_args *args)
 
 static int dump_pages(struct parasite_dump_pages_args *args)
 {
-	int p, ret;
+	int p, ret, tsock;
 	struct iovec *iovs;
 
+	tsock = parasite_get_rpc_sock();
 	p = recv_fd(tsock);
 	if (p < 0)
 		return -1;
@@ -284,8 +283,9 @@ grps_err:
 
 static int drain_fds(struct parasite_drain_fd *args)
 {
-	int ret;
+	int ret, tsock;
 
+	tsock = parasite_get_rpc_sock();
 	ret = send_fds(tsock, NULL, 0,
 		       args->fds, args->nr_fds, true);
 	if (ret)
@@ -354,7 +354,7 @@ static int get_proc_fd(void)
 
 static int parasite_get_proc_fd(void)
 {
-	int fd, ret;
+	int fd, ret, tsock;
 
 	fd = get_proc_fd();
 	if (fd < 0) {
@@ -362,6 +362,7 @@ static int parasite_get_proc_fd(void)
 		return -1;
 	}
 
+	tsock = parasite_get_rpc_sock();
 	ret = send_fd(tsock, NULL, 0, fd);
 	sys_close(fd);
 	return ret;
@@ -565,53 +566,7 @@ static int parasite_dump_cgroup(struct parasite_dump_cgroup_args *args)
 	return 0;
 }
 
-static int __parasite_daemon_reply_ack(unsigned int cmd, int err)
-{
-	struct ctl_msg m;
-	int ret;
-
-	m = ctl_msg_ack(cmd, err);
-	ret = sys_sendto(tsock, &m, sizeof(m), 0, NULL, 0);
-	if (ret != sizeof(m)) {
-		pr_err("Sent only %d bytes while %zu expected\n", ret, sizeof(m));
-		return -1;
-	}
-
-	pr_debug("__sent ack msg: %d %d %d\n",
-		 m.cmd, m.ack, m.err);
-
-	return 0;
-}
-
-static int __parasite_daemon_wait_msg(struct ctl_msg *m)
-{
-	int ret;
-
-	pr_debug("Daemon waits for command\n");
-
-	while (1) {
-		*m = (struct ctl_msg){ };
-		ret = sys_recvfrom(tsock, m, sizeof(*m), MSG_WAITALL, NULL, 0);
-		if (ret != sizeof(*m)) {
-			pr_err("Trimmed message received (%d/%d)\n",
-			       (int)sizeof(*m), ret);
-			return -1;
-		}
-
-		pr_debug("__fetched msg: %d %d %d\n",
-			 m->cmd, m->ack, m->err);
-		return 0;
-	}
-
-	return -1;
-}
-
-static noinline void fini_sigreturn(unsigned long new_sp)
-{
-	ARCH_RT_SIGRETURN(new_sp, sigframe);
-}
-
-static void parasite_cleanup(void)
+void parasite_cleanup(void)
 {
 	if (mprotect_args) {
 		mprotect_args->add_prot = 0;
@@ -619,27 +574,7 @@ static void parasite_cleanup(void)
 	}
 }
 
-static int fini(void)
-{
-	unsigned long new_sp;
-
-	parasite_cleanup();
-
-	new_sp = (long)sigframe + RT_SIGFRAME_OFFSET(sigframe);
-	pr_debug("%ld: new_sp=%lx ip %lx\n", sys_gettid(),
-		  new_sp, RT_SIGFRAME_REGIP(sigframe));
-
-	sys_close(tsock);
-	log_set_fd(-1);
-
-	fini_sigreturn(new_sp);
-
-	BUG();
-
-	return -1;
-}
-
-static int parasite_daemon_cmd(int cmd, void *args)
+int parasite_daemon_cmd(int cmd, void *args)
 {
 	int ret;
 
@@ -692,103 +627,7 @@ static int parasite_daemon_cmd(int cmd, void *args)
 	return ret;
 }
 
-static noinline __used int noinline parasite_daemon(void *args)
-{
-	struct ctl_msg m;
-	int ret = -1;
-
-	pr_debug("Running daemon thread leader\n");
-
-	/* Reply we're alive */
-	if (__parasite_daemon_reply_ack(PARASITE_CMD_INIT_DAEMON, 0))
-		goto out;
-
-	ret = 0;
-
-	while (1) {
-		if (__parasite_daemon_wait_msg(&m))
-			break;
-
-		if (ret && m.cmd != PARASITE_CMD_FINI) {
-			pr_err("Command rejected\n");
-			continue;
-		}
-
-		if (m.cmd == PARASITE_CMD_FINI)
-			goto out;
-
-		ret = parasite_daemon_cmd(m.cmd, args);
-
-		if (__parasite_daemon_reply_ack(m.cmd, ret))
-			break;
-
-		if (ret) {
-			pr_err("Close the control socket for writing\n");
-			sys_shutdown(tsock, SHUT_WR);
-		}
-	}
-
-out:
-	fini();
-
-	return 0;
-}
-
-static noinline int unmap_itself(void *data)
-{
-	struct parasite_unmap_args *args = data;
-
-	sys_munmap((void*)(uintptr_t)args->parasite_start, args->parasite_len);
-	/*
-	 * This call to sys_munmap must never return. Instead, the controlling
-	 * process must trap us on the exit from munmap.
-	 */
-
-	BUG();
-	return -1;
-}
-
-static noinline __used int parasite_init_daemon(void *data)
-{
-	struct parasite_init_args *args = data;
-	int ret;
-
-	args->sigreturn_addr = (u64)(uintptr_t)fini_sigreturn;
-	sigframe = (void*)(uintptr_t)args->sigframe;
-
-	ret = tsock = sys_socket(PF_UNIX, SOCK_SEQPACKET, 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;
-	}
-
-	futex_set_and_wake(&args->daemon_connected, 1);
-
-	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:
-	futex_set_and_wake(&args->daemon_connected, ret);
-	fini();
-	BUG();
-
-	return -1;
-}
-
-static int parasite_trap_cmd(int cmd, void *args)
+int parasite_trap_cmd(int cmd, void *args)
 {
 	switch (cmd) {
 	case PARASITE_CMD_DUMP_THREAD:
@@ -798,39 +637,3 @@ static int parasite_trap_cmd(int cmd, void *args)
 	pr_err("Unknown command to parasite: %d\n", cmd);
 	return -EINVAL;
 }
-
-#ifndef __parasite_entry
-# define __parasite_entry
-#endif
-
-int __used __parasite_entry parasite_service(unsigned int cmd, void *args)
-{
-	pr_info("Parasite cmd %d/%x process\n", cmd, cmd);
-
-	switch (cmd) {
-	case PARASITE_CMD_INIT_DAEMON:
-		return parasite_init_daemon(args);
-	case PARASITE_CMD_UNMAP:
-		return unmap_itself(args);
-	}
-
-	return parasite_trap_cmd(cmd, args);
-}
-
-/*
- * Mainally, -fstack-protector is disabled for parasite.
- * But we share some object files, compiled for CRIU with parasite.
- * Those files (like cpu.c) may be compiled with stack protector
- * support. We can't use gcc-ld provided stackprotector callback,
- * as Glibc is unmapped. Let's just try to cure application in
- * case of stack smashing in parasite.
- */
-void __stack_chk_fail(void)
-{
-	/*
-	 * Smash didn't happen in printing part, as it's not shared
-	 * with CRIU, therefore compiled with -fnostack-protector.
-	 */
-	pr_err("Stack smash detected in parasite\n");
-	fini();
-}
-- 
2.7.4



More information about the CRIU mailing list