[CRIU] [PATCH 19/78] infect: Move infect() into infect.c
Cyrill Gorcunov
gorcunov at openvz.org
Mon Nov 7 08:36:04 PST 2016
From: Pavel Emelyanov <xemul at virtuozzo.com>
Not only infect() routine but all dependant code too. This is
the core of the library actually.
Signed-off-by: Pavel Emelyanov <xemul at virtuozzo.com>
---
criu/cr-exec.c | 2 +-
criu/include/infect-priv.h | 2 +
criu/include/infect.h | 4 +
criu/infect.c | 299 ++++++++++++++++++++++++++++++++++++++++++++-
criu/parasite-syscall.c | 293 +-------------------------------------------
5 files changed, 308 insertions(+), 292 deletions(-)
diff --git a/criu/cr-exec.c b/criu/cr-exec.c
index 870017eb0f02..347e0955b11c 100644
--- a/criu/cr-exec.c
+++ b/criu/cr-exec.c
@@ -2,10 +2,10 @@
#include <string.h>
#include <stdlib.h>
#include "crtools.h"
+#include "parasite-syscall.h"
#include "proc_parse.h"
#include "ptrace.h"
#include "pstree.h"
-#include "parasite-syscall.h"
#include "vma.h"
#include "log.h"
#include "util.h"
diff --git a/criu/include/infect-priv.h b/criu/include/infect-priv.h
index a461ffa2ce9f..8a1ab610db5f 100644
--- a/criu/include/infect-priv.h
+++ b/criu/include/infect-priv.h
@@ -32,4 +32,6 @@ struct parasite_ctl {
int tsock; /* transport socket for transferring fds */
};
+int parasite_run(pid_t pid, int cmd, unsigned long ip, void *stack,
+ user_regs_struct_t *regs, struct thread_ctx *octx);
#endif
diff --git a/criu/include/infect.h b/criu/include/infect.h
index dbd721b14a7a..9cfbfe08482a 100644
--- a/criu/include/infect.h
+++ b/criu/include/infect.h
@@ -23,4 +23,8 @@ extern int compel_wait_task(int pid, int ppid,
#define TASK_STOPPED 0x3
#define TASK_ZOMBIE 0x6
+struct parasite_ctl;
+
+extern int compel_infect(struct parasite_ctl *ctl, unsigned long nr_threads, unsigned long args_size);
+
#endif
diff --git a/criu/infect.c b/criu/infect.c
index 860525c92867..d16a2900b454 100644
--- a/criu/infect.c
+++ b/criu/infect.c
@@ -6,12 +6,23 @@
#include <signal.h>
#include <linux/seccomp.h>
+#include "ptrace.h"
+#include "signal.h"
+#include "asm/parasite-syscall.h"
+#include "asm/dump.h"
+#include "restorer.h"
+#include "parasite.h"
#include "parasite-syscall.h"
-
+#include "pie-relocs.h"
+#include "parasite-blob.h"
+#include "sigframe.h"
#include "log.h"
#include "infect.h"
#include "infect-priv.h"
+/* XXX will be removed soon */
+extern int parasite_wait_ack(int sockfd, unsigned int cmd, struct ctl_msg *m);
+
#define PTRACE_EVENT_STOP 128
#ifndef SECCOMP_MODE_DISABLED
@@ -230,3 +241,289 @@ err:
return -1;
}
+static int gen_parasite_saddr(struct sockaddr_un *saddr, int key)
+{
+ int sun_len;
+
+ saddr->sun_family = AF_UNIX;
+ snprintf(saddr->sun_path, UNIX_PATH_MAX,
+ "X/crtools-pr-%d", key);
+
+ sun_len = SUN_LEN(saddr);
+ *saddr->sun_path = '\0';
+
+ return sun_len;
+}
+
+static int prepare_tsock(struct parasite_ctl *ctl, pid_t pid,
+ struct parasite_init_args *args)
+{
+ static int ssock = -1;
+
+ pr_info("Putting tsock into pid %d\n", pid);
+ args->h_addr_len = gen_parasite_saddr(&args->h_addr, getpid());
+
+ if (ssock == -1) {
+ ssock = *ctl->ictx.p_sock;
+ if (ssock == -1) {
+ pr_err("No socket in ictx\n");
+ goto err;
+ }
+
+ *ctl->ictx.p_sock = -1;
+
+ if (bind(ssock, (struct sockaddr *)&args->h_addr, args->h_addr_len) < 0) {
+ pr_perror("Can't bind socket");
+ goto err;
+ }
+
+ if (listen(ssock, 1)) {
+ pr_perror("Can't listen on transport socket");
+ goto err;
+ }
+ }
+
+ /* Check a case when parasite can't initialize a command socket */
+ if (ctl->ictx.flags & INFECT_FAIL_CONNECT)
+ args->h_addr_len = gen_parasite_saddr(&args->h_addr, getpid() + 1);
+
+ /*
+ * Set to -1 to prevent any accidental misuse. The
+ * only valid user of it is accept_tsock().
+ */
+ ctl->tsock = -ssock;
+ return 0;
+err:
+ close_safe(&ssock);
+ return -1;
+}
+
+static int setup_child_handler(struct parasite_ctl *ctl)
+{
+ struct sigaction sa = {
+ .sa_sigaction = ctl->ictx.child_handler,
+ .sa_flags = SA_SIGINFO | SA_RESTART,
+ };
+
+ sigemptyset(&sa.sa_mask);
+ sigaddset(&sa.sa_mask, SIGCHLD);
+ if (sigaction(SIGCHLD, &sa, NULL)) {
+ pr_perror("Unable to setup SIGCHLD handler");
+ return -1;
+ }
+
+ return 0;
+}
+
+int parasite_run(pid_t pid, int cmd, unsigned long ip, void *stack,
+ user_regs_struct_t *regs, struct thread_ctx *octx)
+{
+ k_rtsigset_t block;
+
+ ksigfillset(&block);
+ if (ptrace(PTRACE_SETSIGMASK, pid, sizeof(k_rtsigset_t), &block)) {
+ pr_perror("Can't block signals for %d", pid);
+ goto err_sig;
+ }
+
+ parasite_setup_regs(ip, stack, regs);
+ if (ptrace_set_regs(pid, regs)) {
+ pr_perror("Can't set registers for %d", pid);
+ goto err_regs;
+ }
+
+ if (ptrace(cmd, pid, NULL, NULL)) {
+ pr_perror("Can't run parasite at %d", pid);
+ goto err_cont;
+ }
+
+ return 0;
+
+err_cont:
+ if (ptrace_set_regs(pid, &octx->regs))
+ pr_perror("Can't restore regs for %d", pid);
+err_regs:
+ if (ptrace(PTRACE_SETSIGMASK, pid, sizeof(k_rtsigset_t), &octx->sigmask))
+ pr_perror("Can't restore sigmask for %d", pid);
+err_sig:
+ return -1;
+}
+
+static int accept_tsock(struct parasite_ctl *ctl)
+{
+ int sock;
+ int ask = -ctl->tsock; /* this '-' is explained above */
+
+ sock = accept(ask, NULL, 0);
+ if (sock < 0) {
+ pr_perror("Can't accept connection to the transport socket");
+ close(ask);
+ return -1;
+ }
+
+ ctl->tsock = sock;
+ return 0;
+}
+
+static int parasite_init_daemon(struct parasite_ctl *ctl)
+{
+ struct parasite_init_args *args;
+ pid_t pid = ctl->rpid;
+ user_regs_struct_t regs;
+ struct ctl_msg m = { };
+
+ *ctl->addr_cmd = PARASITE_CMD_INIT_DAEMON;
+
+ args = parasite_args(ctl, struct parasite_init_args);
+
+ args->sigframe = (uintptr_t)ctl->rsigframe;
+ args->log_level = log_get_loglevel();
+
+ futex_set(&args->daemon_connected, 0);
+
+ if (prepare_tsock(ctl, pid, args))
+ goto err;
+
+ /* after this we can catch parasite errors in chld handler */
+ if (setup_child_handler(ctl))
+ goto err;
+
+ regs = ctl->orig.regs;
+ if (parasite_run(pid, PTRACE_CONT, ctl->parasite_ip, ctl->rstack, ®s, &ctl->orig))
+ 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)
+ 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_INIT_DAEMON, &m)) {
+ pr_err("Can't switch parasite %d to daemon mode %d\n",
+ pid, m.err);
+ goto err;
+ }
+
+ ctl->sigreturn_addr = (void*)(uintptr_t)args->sigreturn_addr;
+ ctl->daemonized = true;
+ pr_info("Parasite %d has been switched to daemon mode\n", pid);
+ return 0;
+err:
+ return -1;
+}
+
+static int parasite_start_daemon(struct parasite_ctl *ctl)
+{
+ pid_t pid = ctl->rpid;
+ struct infect_ctx *ictx = &ctl->ictx;
+
+ /*
+ * Get task registers before going daemon, since the
+ * get_task_regs needs to call ptrace on _stopped_ task,
+ * while in daemon it is not such.
+ */
+
+ if (get_task_regs(pid, ctl->orig.regs, ictx->save_regs, ictx->regs_arg)) {
+ pr_err("Can't obtain regs for thread %d\n", pid);
+ return -1;
+ }
+
+ if (ictx->make_sigframe(ictx->regs_arg, ctl->sigframe, ctl->rsigframe, &ctl->orig.sigmask))
+ return -1;
+
+ if (parasite_init_daemon(ctl))
+ return -1;
+
+ return 0;
+}
+
+#define init_parasite_ctl(ctl, blob_type) \
+ do { \
+ memcpy(ctl->local_map, parasite_##blob_type##_blob, \
+ sizeof(parasite_##blob_type##_blob)); \
+ ELF_RELOCS_APPLY(parasite_##blob_type, \
+ ctl->local_map, ctl->remote_map); \
+ /* Setup the rest of a control block */ \
+ ctl->parasite_ip = (unsigned long)parasite_sym(ctl->remote_map, \
+ blob_type, __export_parasite_head_start); \
+ ctl->addr_cmd = parasite_sym(ctl->local_map, blob_type, \
+ __export_parasite_cmd); \
+ ctl->addr_args = parasite_sym(ctl->local_map, blob_type, \
+ __export_parasite_args); \
+ } while (0)
+
+int compel_infect(struct parasite_ctl *ctl, unsigned long nr_threads, unsigned long args_size)
+{
+ int ret;
+ unsigned long p, map_exchange_size, parasite_size = 0;
+
+ if (!arch_can_dump_task(ctl))
+ goto err;
+
+ /*
+ * Inject a parasite engine. Ie allocate memory inside alien
+ * space and copy engine code there. Then re-map the engine
+ * locally, so we will get an easy way to access engine memory
+ * without using ptrace at all.
+ */
+
+ if (seized_native(ctl))
+ parasite_size = pie_size(parasite_native);
+#ifdef CONFIG_COMPAT
+ else
+ parasite_size = pie_size(parasite_compat);
+#endif
+
+ ctl->args_size = round_up(args_size, PAGE_SIZE);
+ parasite_size += ctl->args_size;
+
+ map_exchange_size = parasite_size;
+ map_exchange_size += RESTORE_STACK_SIGFRAME + PARASITE_STACK_SIZE;
+ if (nr_threads > 1)
+ map_exchange_size += PARASITE_STACK_SIZE;
+
+ ret = parasite_map_exchange(ctl, map_exchange_size);
+ if (ret)
+ goto err;
+
+ pr_info("Putting parasite blob into %p->%p\n", ctl->local_map, ctl->remote_map);
+
+ if (seized_native(ctl))
+ init_parasite_ctl(ctl, native);
+#ifdef CONFIG_COMPAT
+ else
+ init_parasite_ctl(ctl, compat);
+#endif
+
+ p = parasite_size;
+
+ ctl->rsigframe = ctl->remote_map + p;
+ ctl->sigframe = ctl->local_map + p;
+
+ p += RESTORE_STACK_SIGFRAME;
+ p += PARASITE_STACK_SIZE;
+ ctl->rstack = ctl->remote_map + p;
+
+ if (nr_threads > 1) {
+ p += PARASITE_STACK_SIZE;
+ ctl->r_thread_stack = ctl->remote_map + p;
+ }
+
+ if (parasite_start_daemon(ctl))
+ goto err;
+
+ return 0;
+
+err:
+ return -1;
+}
+
diff --git a/criu/parasite-syscall.c b/criu/parasite-syscall.c
index 771bc3fbfec0..7b38365955d5 100644
--- a/criu/parasite-syscall.c
+++ b/criu/parasite-syscall.c
@@ -16,7 +16,6 @@
#include "imgset.h"
#include "ptrace.h"
#include "parasite-syscall.h"
-#include "parasite-blob.h"
#include "parasite.h"
#include "crtools.h"
#include "namespaces.h"
@@ -42,6 +41,7 @@
#include "restorer.h"
#include "pie/pie-relocs.h"
+#include "infect.h"
#include "infect-priv.h"
#define MEMFD_FNAME "CRIUMFD"
@@ -126,39 +126,6 @@ bool seized_native(struct parasite_ctl *ctl)
{
return user_regs_native(&ctl->orig.regs);
}
-static int parasite_run(pid_t pid, int cmd, unsigned long ip, void *stack,
- user_regs_struct_t *regs, struct thread_ctx *octx)
-{
- k_rtsigset_t block;
-
- ksigfillset(&block);
- if (ptrace(PTRACE_SETSIGMASK, pid, sizeof(k_rtsigset_t), &block)) {
- pr_perror("Can't block signals for %d", pid);
- goto err_sig;
- }
-
- parasite_setup_regs(ip, stack, regs);
- if (ptrace_set_regs(pid, regs)) {
- pr_perror("Can't set registers for %d", pid);
- goto err_regs;
- }
-
- if (ptrace(cmd, pid, NULL, NULL)) {
- pr_perror("Can't run parasite at %d", pid);
- goto err_cont;
- }
-
- return 0;
-
-err_cont:
- if (ptrace_set_regs(pid, &octx->regs))
- pr_perror("Can't restore regs for %d", pid);
-err_regs:
- if (ptrace(PTRACE_SETSIGMASK, pid, sizeof(k_rtsigset_t), &octx->sigmask))
- pr_perror("Can't restore sigmask for %d", pid);
-err_sig:
- return -1;
-}
/* we run at @regs->ip */
static int parasite_trap(struct parasite_ctl *ctl, pid_t pid,
@@ -296,7 +263,7 @@ static int __parasite_send_cmd(int sockfd, struct ctl_msg *m)
return 0;
}
-static int parasite_wait_ack(int sockfd, unsigned int cmd, struct ctl_msg *m)
+int parasite_wait_ack(int sockfd, unsigned int cmd, struct ctl_msg *m)
{
int ret;
@@ -364,20 +331,6 @@ int parasite_execute_daemon(unsigned int cmd, struct parasite_ctl *ctl)
return ret;
}
-static int gen_parasite_saddr(struct sockaddr_un *saddr, int key)
-{
- int sun_len;
-
- saddr->sun_family = AF_UNIX;
- snprintf(saddr->sun_path, UNIX_PATH_MAX,
- "X/crtools-pr-%d", key);
-
- sun_len = SUN_LEN(saddr);
- *saddr->sun_path = '\0';
-
- return sun_len;
-}
-
int parasite_send_fd(struct parasite_ctl *ctl, int fd)
{
if (send_fd(ctl->tsock, NULL, 0, fd) < 0) {
@@ -418,23 +371,6 @@ static void sigchld_handler(int signal, siginfo_t *siginfo, void *data)
exit(1);
}
-static int setup_child_handler(struct parasite_ctl *ctl)
-{
- struct sigaction sa = {
- .sa_sigaction = ctl->ictx.child_handler,
- .sa_flags = SA_SIGINFO | SA_RESTART,
- };
-
- sigemptyset(&sa.sa_mask);
- sigaddset(&sa.sa_mask, SIGCHLD);
- if (sigaction(SIGCHLD, &sa, NULL)) {
- pr_perror("Unable to setup SIGCHLD handler");
- return -1;
- }
-
- return 0;
-}
-
static int restore_child_handler()
{
struct sigaction sa = {
@@ -452,121 +388,6 @@ static int restore_child_handler()
return 0;
}
-static int prepare_tsock(struct parasite_ctl *ctl, pid_t pid,
- struct parasite_init_args *args)
-{
- static int ssock = -1;
-
- pr_info("Putting tsock into pid %d\n", pid);
- args->h_addr_len = gen_parasite_saddr(&args->h_addr, getpid());
-
- if (ssock == -1) {
- ssock = *ctl->ictx.p_sock;
- if (ssock == -1) {
- pr_err("No socket in ictx\n");
- goto err;
- }
-
- *ctl->ictx.p_sock = -1;
-
- if (bind(ssock, (struct sockaddr *)&args->h_addr, args->h_addr_len) < 0) {
- pr_perror("Can't bind socket");
- goto err;
- }
-
- if (listen(ssock, 1)) {
- pr_perror("Can't listen on transport socket");
- goto err;
- }
- }
-
- /* Check a case when parasite can't initialize a command socket */
- if (ctl->ictx.flags & INFECT_FAIL_CONNECT)
- args->h_addr_len = gen_parasite_saddr(&args->h_addr, getpid() + 1);
-
- /*
- * Set to -1 to prevent any accidental misuse. The
- * only valid user of it is accept_tsock().
- */
- ctl->tsock = -ssock;
- return 0;
-err:
- close_safe(&ssock);
- return -1;
-}
-
-static int accept_tsock(struct parasite_ctl *ctl)
-{
- int sock;
- int ask = -ctl->tsock; /* this '-' is explained above */
-
- sock = accept(ask, NULL, 0);
- if (sock < 0) {
- pr_perror("Can't accept connection to the transport socket");
- close(ask);
- return -1;
- }
-
- ctl->tsock = sock;
- return 0;
-}
-
-static int parasite_init_daemon(struct parasite_ctl *ctl)
-{
- struct parasite_init_args *args;
- pid_t pid = ctl->rpid;
- user_regs_struct_t regs;
- struct ctl_msg m = { };
-
- *ctl->addr_cmd = PARASITE_CMD_INIT_DAEMON;
-
- args = parasite_args(ctl, struct parasite_init_args);
-
- args->sigframe = (uintptr_t)ctl->rsigframe;
- args->log_level = log_get_loglevel();
-
- futex_set(&args->daemon_connected, 0);
-
- if (prepare_tsock(ctl, pid, args))
- goto err;
-
- /* after this we can catch parasite errors in chld handler */
- if (setup_child_handler(ctl))
- goto err;
-
- regs = ctl->orig.regs;
- if (parasite_run(pid, PTRACE_CONT, ctl->parasite_ip, ctl->rstack, ®s, &ctl->orig))
- 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)
- 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_INIT_DAEMON, &m)) {
- pr_err("Can't switch parasite %d to daemon mode %d\n",
- pid, m.err);
- goto err;
- }
-
- ctl->sigreturn_addr = (void*)(uintptr_t)args->sigreturn_addr;
- ctl->daemonized = true;
- pr_info("Parasite %d has been switched to daemon mode\n", pid);
- return 0;
-err:
- return -1;
-}
-
static int alloc_groups_copy_creds(CredsEntry *ce, struct parasite_dump_creds *c)
{
BUILD_BUG_ON(sizeof(ce->groups[0]) != sizeof(c->groups[0]));
@@ -1426,53 +1247,11 @@ void parasite_ensure_args_size(unsigned long sz)
parasite_args_size = sz;
}
-static int parasite_start_daemon(struct parasite_ctl *ctl)
-{
- pid_t pid = ctl->rpid;
- struct infect_ctx *ictx = &ctl->ictx;
-
- /*
- * Get task registers before going daemon, since the
- * get_task_regs needs to call ptrace on _stopped_ task,
- * while in daemon it is not such.
- */
-
- if (get_task_regs(pid, ctl->orig.regs, ictx->save_regs, ictx->regs_arg)) {
- pr_err("Can't obtain regs for thread %d\n", pid);
- return -1;
- }
-
- if (ictx->make_sigframe(ictx->regs_arg, ctl->sigframe, ctl->rsigframe, &ctl->orig.sigmask))
- return -1;
-
- if (parasite_init_daemon(ctl))
- return -1;
-
- return 0;
-}
-
-#define init_parasite_ctl(ctl, blob_type) \
- do { \
- memcpy(ctl->local_map, parasite_##blob_type##_blob, \
- sizeof(parasite_##blob_type##_blob)); \
- ELF_RELOCS_APPLY(parasite_##blob_type, \
- ctl->local_map, ctl->remote_map); \
- /* Setup the rest of a control block */ \
- ctl->parasite_ip = (unsigned long)parasite_sym(ctl->remote_map, \
- blob_type, __export_parasite_head_start); \
- ctl->addr_cmd = parasite_sym(ctl->local_map, blob_type, \
- __export_parasite_cmd); \
- ctl->addr_args = parasite_sym(ctl->local_map, blob_type, \
- __export_parasite_args); \
- } while (0)
-
static int make_sigframe(void *arg, struct rt_sigframe *sf, struct rt_sigframe *rtsf, k_rtsigset_t *bs)
{
return construct_sigframe(sf, rtsf, bs, (CoreEntry *)arg);
}
-static int infect(struct parasite_ctl *ctl, unsigned long nr_threads, unsigned long args_size);
-
struct parasite_ctl *parasite_infect_seized(pid_t pid, struct pstree_item *item,
struct vm_area_list *vma_area_list)
{
@@ -1507,7 +1286,7 @@ struct parasite_ctl *parasite_infect_seized(pid_t pid, struct pstree_item *item,
parasite_ensure_args_size(dump_pages_args_size(vma_area_list));
parasite_ensure_args_size(aio_rings_args_size(vma_area_list));
- if (infect(ctl, item->nr_threads, parasite_args_size) < 0) {
+ if (compel_infect(ctl, item->nr_threads, parasite_args_size) < 0) {
parasite_cure_seized(ctl);
return NULL;
}
@@ -1519,72 +1298,6 @@ struct parasite_ctl *parasite_infect_seized(pid_t pid, struct pstree_item *item,
return ctl;
}
-static int infect(struct parasite_ctl *ctl, unsigned long nr_threads, unsigned long args_size)
-{
- int ret;
- unsigned long p, map_exchange_size, parasite_size = 0;
-
- if (!arch_can_dump_task(ctl))
- goto err;
-
- /*
- * Inject a parasite engine. Ie allocate memory inside alien
- * space and copy engine code there. Then re-map the engine
- * locally, so we will get an easy way to access engine memory
- * without using ptrace at all.
- */
-
- if (seized_native(ctl))
- parasite_size = pie_size(parasite_native);
-#ifdef CONFIG_COMPAT
- else
- parasite_size = pie_size(parasite_compat);
-#endif
-
- ctl->args_size = round_up(args_size, PAGE_SIZE);
- parasite_size += ctl->args_size;
-
- map_exchange_size = parasite_size;
- map_exchange_size += RESTORE_STACK_SIGFRAME + PARASITE_STACK_SIZE;
- if (nr_threads > 1)
- map_exchange_size += PARASITE_STACK_SIZE;
-
- ret = parasite_map_exchange(ctl, map_exchange_size);
- if (ret)
- goto err;
-
- pr_info("Putting parasite blob into %p->%p\n", ctl->local_map, ctl->remote_map);
-
- if (seized_native(ctl))
- init_parasite_ctl(ctl, native);
-#ifdef CONFIG_COMPAT
- else
- init_parasite_ctl(ctl, compat);
-#endif
-
- p = parasite_size;
-
- ctl->rsigframe = ctl->remote_map + p;
- ctl->sigframe = ctl->local_map + p;
-
- p += RESTORE_STACK_SIGFRAME;
- p += PARASITE_STACK_SIZE;
- ctl->rstack = ctl->remote_map + p;
-
- if (nr_threads > 1) {
- p += PARASITE_STACK_SIZE;
- ctl->r_thread_stack = ctl->remote_map + p;
- }
-
- if (parasite_start_daemon(ctl))
- goto err;
-
- return 0;
-
-err:
- return -1;
-}
-
int ptrace_stop_pie(pid_t pid, void *addr, enum trace_flags *tf)
{
int ret;
--
2.7.4
More information about the CRIU
mailing list