[CRIU] [PATCH 06/15] parasite: add a function for unmaping bootstrap blob

Andrey Vagin avagin at openvz.org
Mon Sep 23 06:33:29 EDT 2013


The munmap syscall must be executed from a process memory. The code can
be injected in memory and then removed. But we can avoid all these
actions, if the code will be in the blob and a process will be trapped
on the exit from the munmap syscall.

Signed-off-by: Andrey Vagin <avagin at openvz.org>
---
 include/parasite-syscall.h |  1 +
 parasite-syscall.c         | 47 +++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 47 insertions(+), 1 deletion(-)

diff --git a/include/parasite-syscall.h b/include/parasite-syscall.h
index 3515a30..2f4ca82 100644
--- a/include/parasite-syscall.h
+++ b/include/parasite-syscall.h
@@ -115,4 +115,5 @@ extern int parasite_fixup_vdso(struct parasite_ctl *ctl, pid_t pid,
 			       struct vm_area_list *vma_area_list);
 
 extern int parasite_stop_on_syscall(int tasks, int sys_nr);
+extern int parasite_unmap(struct parasite_ctl *ctl, unsigned long addr);
 #endif /* __CR_PARASITE_SYSCALL_H__ */
diff --git a/parasite-syscall.c b/parasite-syscall.c
index 8be6e5e..48d0785 100644
--- a/parasite-syscall.c
+++ b/parasite-syscall.c
@@ -886,8 +886,53 @@ int parasite_cure_seized(struct parasite_ctl *ctl)
 }
 
 /*
- * If vma_area_list is NULL, a place for injecting syscall will not be set.
+ * parasite_unmap() is used for unmapping parasite and restorer blobs.
+ * A blob can contain code for unmapping itself, so the porcess is
+ * trapped on the exit from the munmap syscall.
  */
+int parasite_unmap(struct parasite_ctl *ctl, unsigned long addr)
+{
+	user_regs_struct_t regs;
+	pid_t pid = ctl->pid.real;
+	k_rtsigset_t block;
+	int ret = -1;
+
+	ksigfillset(&block);
+
+	if (ptrace(PTRACE_SETSIGMASK, pid, sizeof(k_rtsigset_t), &block)) {
+		pr_perror("Can't block signals for %d", pid);
+		goto err;
+	}
+
+	regs = ctl->regs_orig;
+	parasite_setup_regs(addr, 0, &regs);
+	if (ptrace(PTRACE_SETREGS, pid, NULL, &regs)) {
+		pr_perror("Can't set registers for %d", pid);
+		goto err_sig;
+	}
+
+	if (ptrace(PTRACE_SYSCALL, pid, NULL, NULL)) {
+		pr_perror("ptrace");
+		goto err_regs;
+	}
+
+	ret = parasite_stop_on_syscall(1, __NR_munmap);
+
+err_regs:
+	if (ptrace(PTRACE_SETREGS, pid, NULL, &ctl->regs_orig)) {
+		pr_perror("Can't restore regs for %d", pid);
+		ret = -1;
+	}
+err_sig:
+	if (ptrace(PTRACE_SETSIGMASK, pid, sizeof(k_rtsigset_t), &ctl->sig_blocked)) {
+		pr_perror("Can't restore sigmask for %d", pid);
+		ret = -1;
+	}
+err:
+	return ret;
+}
+
+/* If vma_area_list is NULL, a place for injecting syscall will not be set. */
 struct parasite_ctl *parasite_prep_ctl(pid_t pid, struct vm_area_list *vma_area_list)
 {
 	struct parasite_ctl *ctl = NULL;
-- 
1.8.3.1



More information about the CRIU mailing list