[2/8] compel: Introduce parasite_thread_ctl

Submitted by Pavel Emelianov on Nov. 14, 2016, 1:05 p.m.

Details

Message ID 5829B684.4060506@virtuozzo.com
State Accepted
Series "compel: Sanitize API after split, wave 1"
Commit 2bfb151fae4cb0804bfb18c219c08457e5a50388
Headers show

Commit Message

Pavel Emelianov Nov. 14, 2016, 1:05 p.m.
The structure is opaque hander for thread infection.

Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
---
 compel/include/uapi/infect.h | 11 ++++++++---
 compel/src/lib/infect.c      | 42 +++++++++++++++++++++++++++++++++++++-----
 criu/parasite-syscall.c      | 24 +++++++++++++++---------
 3 files changed, 60 insertions(+), 17 deletions(-)

Patch hide | download patch | download mbox

diff --git a/compel/include/uapi/infect.h b/compel/include/uapi/infect.h
index c444a6e..d7ef921 100644
--- a/compel/include/uapi/infect.h
+++ b/compel/include/uapi/infect.h
@@ -42,9 +42,14 @@  struct thread_ctx {
 	user_regs_struct_t	regs;
 };
 
+struct parasite_thread_ctl {
+	struct thread_ctx	th;
+};
+
 extern struct parasite_ctl *compel_prepare(int pid);
 extern int compel_infect(struct parasite_ctl *ctl, unsigned long nr_threads, unsigned long args_size);
-extern int compel_prepare_thread(int pid, struct thread_ctx *ctx);
+extern struct parasite_thread_ctl *compel_prepare_thread(struct parasite_ctl *ctl, int pid);
+extern void compel_release_thread(struct parasite_thread_ctl *);
 
 extern int compel_stop_daemon(struct parasite_ctl *ctl);
 extern int compel_cure_remote(struct parasite_ctl *ctl);
@@ -68,7 +73,7 @@  extern int compel_execute_syscall(struct parasite_ctl *ctl,
 		user_regs_struct_t *regs, const char *code_syscall);
 extern int compel_run_in_thread(pid_t pid, unsigned int cmd,
 					struct parasite_ctl *ctl,
-					struct thread_ctx *octx);
+					struct parasite_thread_ctl *tctl);
 
 /*
  * The PTRACE_SYSCALL will trap task twice -- on
@@ -92,7 +97,7 @@  extern int compel_unmap(struct parasite_ctl *ctl, unsigned long addr);
 extern int compel_mode_native(struct parasite_ctl *ctl);
 
 extern k_rtsigset_t *compel_task_sigmask(struct parasite_ctl *ctl);
-extern k_rtsigset_t *compel_thread_sigmask(struct thread_ctx *tctx);
+extern k_rtsigset_t *compel_thread_sigmask(struct parasite_thread_ctl *tctl);
 
 struct rt_sigframe;
 
diff --git a/compel/src/lib/infect.c b/compel/src/lib/infect.c
index ff2140d..a3e0241 100644
--- a/compel/src/lib/infect.c
+++ b/compel/src/lib/infect.c
@@ -45,6 +45,8 @@ 
 
 #define SI_EVENT(_si_code)	(((_si_code) & 0xFFFF) >> 8)
 
+static int prepare_thread(int pid, struct thread_ctx *ctx);
+
 static inline void close_safe(int *pfd)
 {
 	if (*pfd > -1) {
@@ -836,7 +838,22 @@  err:
 	return -1;
 }
 
-int compel_prepare_thread(int pid, struct thread_ctx *ctx)
+struct parasite_thread_ctl *compel_prepare_thread(struct parasite_ctl *ctl, int pid)
+{
+	struct parasite_thread_ctl *tctl;
+
+	tctl = xmalloc(sizeof(*tctl));
+	if (tctl) {
+		if (prepare_thread(pid, &tctl->th)) {
+			xfree(tctl);
+			tctl = NULL;
+		}
+	}
+
+	return tctl;
+}
+
+static int prepare_thread(int pid, struct thread_ctx *ctx)
 {
 	if (ptrace(PTRACE_GETSIGMASK, pid, sizeof(k_rtsigset_t), &ctx->sigmask)) {
 		pr_perror("can't get signal blocking mask for %d", pid);
@@ -851,6 +868,15 @@  int compel_prepare_thread(int pid, struct thread_ctx *ctx)
 	return 0;
 }
 
+void compel_release_thread(struct parasite_thread_ctl *tctl)
+{
+	/*
+	 * No stuff to cure in thread here, all routines leave the
+	 * guy intact (for now)
+	 */
+	xfree(tctl);
+}
+
 struct parasite_ctl *compel_prepare(int pid)
 {
 	struct parasite_ctl *ctl = NULL;
@@ -867,7 +893,7 @@  struct parasite_ctl *compel_prepare(int pid)
 	ctl->tsock = -1;
 	ctl->ictx.log_fd = -1;
 
-	if (compel_prepare_thread(pid, &ctl->orig))
+	if (prepare_thread(pid, &ctl->orig))
 		goto err;
 
 	ctl->rpid = pid;
@@ -1050,8 +1076,9 @@  void *compel_parasite_args_s(struct parasite_ctl *ctl, int args_size)
 
 int compel_run_in_thread(pid_t pid, unsigned int cmd,
 					struct parasite_ctl *ctl,
-					struct thread_ctx *octx)
+					struct parasite_thread_ctl *tctl)
 {
+	struct thread_ctx *octx = &tctl->th;
 	void *stack = ctl->r_thread_stack;
 	user_regs_struct_t regs = octx->regs;
 	int ret;
@@ -1246,14 +1273,19 @@  int compel_mode_native(struct parasite_ctl *ctl)
 	return user_regs_native(&ctl->orig.regs);
 }
 
-k_rtsigset_t *compel_thread_sigmask(struct thread_ctx *tctx)
+static inline k_rtsigset_t *thread_ctx_sigmask(struct thread_ctx *tctx)
 {
 	return &tctx->sigmask;
 }
 
+k_rtsigset_t *compel_thread_sigmask(struct parasite_thread_ctl *tctl)
+{
+	return thread_ctx_sigmask(&tctl->th);
+}
+
 k_rtsigset_t *compel_task_sigmask(struct parasite_ctl *ctl)
 {
-	return compel_thread_sigmask(&ctl->orig);
+	return thread_ctx_sigmask(&ctl->orig);
 }
 
 struct infect_ctx *compel_infect_ctx(struct parasite_ctl *ctl)
diff --git a/criu/parasite-syscall.c b/criu/parasite-syscall.c
index f35b71d..4b265f1 100644
--- a/criu/parasite-syscall.c
+++ b/criu/parasite-syscall.c
@@ -182,7 +182,7 @@  int parasite_dump_thread_seized(struct parasite_ctl *ctl, int id,
 	CredsEntry *creds = tc->creds;
 	struct parasite_dump_creds *pc;
 	int ret;
-	struct thread_ctx octx;
+	struct parasite_thread_ctl *tctl;
 
 	BUG_ON(id == 0); /* Leader is dumped in dump_task_core_all */
 
@@ -196,31 +196,33 @@  int parasite_dump_thread_seized(struct parasite_ctl *ctl, int id,
 
 	pc->cap_last_cap = kdat.last_cap;
 
-	ret = compel_prepare_thread(pid, &octx);
-	if (ret)
+	tctl = compel_prepare_thread(ctl, pid);
+	if (!tctl)
 		return -1;
 
 	tc->has_blk_sigset = true;
-	memcpy(&tc->blk_sigset, compel_thread_sigmask(&octx), sizeof(k_rtsigset_t));
+	memcpy(&tc->blk_sigset, compel_thread_sigmask(tctl), sizeof(k_rtsigset_t));
 
-	ret = compel_run_in_thread(pid, PARASITE_CMD_DUMP_THREAD, ctl, &octx);
+	ret = compel_run_in_thread(pid, PARASITE_CMD_DUMP_THREAD, ctl, tctl);
 	if (ret) {
 		pr_err("Can't init thread in parasite %d\n", pid);
-		return -1;
+		goto err_rth;
 	}
 
 	ret = alloc_groups_copy_creds(creds, pc);
 	if (ret) {
 		pr_err("Can't copy creds for thread %d\n", pid);
-		return -1;
+		goto err_rth;
 	}
 
-	ret = compel_get_task_regs(pid, octx.regs, save_task_regs, core);
+	ret = compel_get_task_regs(pid, tctl->th.regs, save_task_regs, core);
 	if (ret) {
 		pr_err("Can't obtain regs for thread %d\n", pid);
-		return -1;
+		goto err_rth;
 	}
 
+	compel_release_thread(tctl);
+
 	if (compel_mode_native(ctl)) {
 		tid->virt = args->tid;
 		return dump_thread_core(pid, core, true, args);
@@ -228,6 +230,10 @@  int parasite_dump_thread_seized(struct parasite_ctl *ctl, int id,
 		tid->virt = args_c->tid;
 		return dump_thread_core(pid, core, false, args_c);
 	}
+
+err_rth:
+	compel_release_thread(tctl);
+	return -1;
 }
 
 #define ASSIGN_SAS(se, args)							\