[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