[CRIU] [PATCH 37/78] infect: Move mmap_seized() and syscall_seized() into arch/infect.c

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


From: Pavel Emelyanov <xemul at virtuozzo.com>

Signed-off-by: Pavel Emelyanov <xemul at virtuozzo.com>
---
 criu/arch/aarch64/crtools.c                      | 60 ---------------
 criu/arch/aarch64/include/asm/parasite-syscall.h |  4 -
 criu/arch/aarch64/infect.c                       | 59 +++++++++++++++
 criu/arch/arm/crtools.c                          | 60 ---------------
 criu/arch/arm/include/asm/parasite-syscall.h     |  4 -
 criu/arch/arm/infect.c                           | 60 +++++++++++++++
 criu/arch/ppc64/crtools.c                        | 54 --------------
 criu/arch/ppc64/include/asm/parasite-syscall.h   |  4 -
 criu/arch/ppc64/infect.c                         | 54 ++++++++++++++
 criu/arch/x86/crtools.c                          | 89 -----------------------
 criu/arch/x86/include/asm/parasite-syscall.h     |  4 -
 criu/arch/x86/infect.c                           | 93 ++++++++++++++++++++++++
 criu/cr-exec.c                                   |  2 +-
 criu/include/infect-priv.h                       |  9 +++
 criu/include/parasite-syscall.h                  |  5 --
 criu/infect.c                                    | 14 ++--
 16 files changed, 283 insertions(+), 292 deletions(-)

diff --git a/criu/arch/aarch64/crtools.c b/criu/arch/aarch64/crtools.c
index b3e5e55fcee7..e7e7be9c3403 100644
--- a/criu/arch/aarch64/crtools.c
+++ b/criu/arch/aarch64/crtools.c
@@ -20,23 +20,6 @@
 #include "infect.h"
 #include "infect-priv.h"
 
-/*
- * Injected syscall instruction
- */
-const char code_syscall[] = {
-	0x01, 0x00, 0x00, 0xd4,		/* SVC #0 */
-	0x00, 0x00, 0x20, 0xd4		/* BRK #0 */
-};
-
-static const int
-code_syscall_aligned = round_up(sizeof(code_syscall), sizeof(long));
-
-static inline void __always_unused __check_code_syscall(void)
-{
-	BUILD_BUG_ON(code_syscall_aligned != BUILTIN_SYSCALL_SIZE);
-	BUILD_BUG_ON(!is_log2(sizeof(code_syscall)));
-}
-
 void parasite_setup_regs(unsigned long new_ip, void *stack, user_regs_struct_t *regs)
 {
 	regs->pc = new_ip;
@@ -52,33 +35,6 @@ bool arch_can_dump_task(struct parasite_ctl *ctl)
 	return true;
 }
 
-int syscall_seized(struct parasite_ctl *ctl, int nr, unsigned long *ret,
-					unsigned long arg1,
-					unsigned long arg2,
-					unsigned long arg3,
-					unsigned long arg4,
-					unsigned long arg5,
-					unsigned long arg6)
-{
-	user_regs_struct_t regs = ctl->orig.regs;
-	int err;
-
-	regs.regs[8] = (unsigned long)nr;
-	regs.regs[0] = arg1;
-	regs.regs[1] = arg2;
-	regs.regs[2] = arg3;
-	regs.regs[3] = arg4;
-	regs.regs[4] = arg5;
-	regs.regs[5] = arg6;
-	regs.regs[6] = 0;
-	regs.regs[7] = 0;
-
-	err = compel_execute_syscall(ctl, &regs, code_syscall);
-
-	*ret = regs.regs[0];
-	return err;
-}
-
 #define assign_reg(dst, src, e)		dst->e = (__typeof__(dst->e))(src)->e
 
 int save_task_regs(void *x, user_regs_struct_t *regs, user_fpregs_struct_t *fpsimd)
@@ -179,22 +135,6 @@ int restore_fpu(struct rt_sigframe *sigframe, CoreEntry *core)
 	return 0;
 }
 
-void *mmap_seized(
-		struct parasite_ctl *ctl,
-		void *addr, size_t length, int prot,
-		int flags, int fd, off_t offset)
-{
-	unsigned long map;
-	int err;
-
-	err = syscall_seized(ctl, __NR_mmap, &map,
-			(unsigned long)addr, length, prot, flags, fd, offset);
-	if (err < 0 || (long)map < 0)
-		map = 0;
-
-	return (void *)map;
-}
-
 int restore_gpregs(struct rt_sigframe *f, UserRegsEntry *r)
 {
 #define CPREG1(d)       f->uc.uc_mcontext.d = r->d
diff --git a/criu/arch/aarch64/include/asm/parasite-syscall.h b/criu/arch/aarch64/include/asm/parasite-syscall.h
index 7a5591ad5c7c..e420ccbdc625 100644
--- a/criu/arch/aarch64/include/asm/parasite-syscall.h
+++ b/criu/arch/aarch64/include/asm/parasite-syscall.h
@@ -9,8 +9,4 @@ struct parasite_ctl;
 
 void parasite_setup_regs(unsigned long new_ip, void *stack, user_regs_struct_t *regs);
 
-void *mmap_seized(struct parasite_ctl *ctl,
-		  void *addr, size_t length, int prot,
-		  int flags, int fd, off_t offset);
-
 #endif
diff --git a/criu/arch/aarch64/infect.c b/criu/arch/aarch64/infect.c
index 92b3c73b1e48..2411cd6e8392 100644
--- a/criu/arch/aarch64/infect.c
+++ b/criu/arch/aarch64/infect.c
@@ -12,6 +12,23 @@
 #include "infect.h"
 #include "infect-priv.h"
 
+/*
+ * Injected syscall instruction
+ */
+const char code_syscall[] = {
+	0x01, 0x00, 0x00, 0xd4,		/* SVC #0 */
+	0x00, 0x00, 0x20, 0xd4		/* BRK #0 */
+};
+
+static const int
+code_syscall_aligned = round_up(sizeof(code_syscall), sizeof(long));
+
+static inline void __always_unused __check_code_syscall(void)
+{
+	BUILD_BUG_ON(code_syscall_aligned != BUILTIN_SYSCALL_SIZE);
+	BUILD_BUG_ON(!is_log2(sizeof(code_syscall)));
+}
+
 int compel_get_task_regs(pid_t pid, user_regs_struct_t regs, save_regs_t save, void *arg)
 {
 	struct iovec iov;
@@ -39,3 +56,45 @@ err:
 	return ret;
 }
 
+int compel_syscall(struct parasite_ctl *ctl, int nr, unsigned long *ret,
+					unsigned long arg1,
+					unsigned long arg2,
+					unsigned long arg3,
+					unsigned long arg4,
+					unsigned long arg5,
+					unsigned long arg6)
+{
+	user_regs_struct_t regs = ctl->orig.regs;
+	int err;
+
+	regs.regs[8] = (unsigned long)nr;
+	regs.regs[0] = arg1;
+	regs.regs[1] = arg2;
+	regs.regs[2] = arg3;
+	regs.regs[3] = arg4;
+	regs.regs[4] = arg5;
+	regs.regs[5] = arg6;
+	regs.regs[6] = 0;
+	regs.regs[7] = 0;
+
+	err = compel_execute_syscall(ctl, &regs, code_syscall);
+
+	*ret = regs.regs[0];
+	return err;
+}
+
+void *mmap_re(struct parasite_ctl *ctl,
+		void *addr, size_t length, int prot,
+		int flags, int fd, off_t offset)
+{
+	unsigned long map;
+	int err;
+
+	err = compel_syscall(ctl, __NR_mmap, &map,
+			(unsigned long)addr, length, prot, flags, fd, offset);
+	if (err < 0 || (long)map < 0)
+		map = 0;
+
+	return (void *)map;
+}
+
diff --git a/criu/arch/arm/crtools.c b/criu/arch/arm/crtools.c
index fb267fe85072..78fa02a99082 100644
--- a/criu/arch/arm/crtools.c
+++ b/criu/arch/arm/crtools.c
@@ -21,23 +21,6 @@
 #include "infect.h"
 #include "infect-priv.h"
 
-/*
- * Injected syscall instruction
- */
-const char code_syscall[] = {
-	0x00, 0x00, 0x00, 0xef,         /* SVC #0  */
-	0xf0, 0x01, 0xf0, 0xe7          /* UDF #32 */
-};
-
-static const int
-code_syscall_aligned = round_up(sizeof(code_syscall), sizeof(long));
-
-static inline __always_unused void __check_code_syscall(void)
-{
-	BUILD_BUG_ON(code_syscall_aligned != BUILTIN_SYSCALL_SIZE);
-	BUILD_BUG_ON(!is_log2(sizeof(code_syscall)));
-}
-
 void parasite_setup_regs(unsigned long new_ip, void *stack, user_regs_struct_t *regs)
 {
 	regs->ARM_pc = new_ip;
@@ -56,31 +39,6 @@ bool arch_can_dump_task(struct parasite_ctl *ctl)
 	return true;
 }
 
-int syscall_seized(struct parasite_ctl *ctl, int nr, unsigned long *ret,
-		unsigned long arg1,
-		unsigned long arg2,
-		unsigned long arg3,
-		unsigned long arg4,
-		unsigned long arg5,
-		unsigned long arg6)
-{
-	user_regs_struct_t regs = ctl->orig.regs;
-	int err;
-
-	regs.ARM_r7 = (unsigned long)nr;
-	regs.ARM_r0 = arg1;
-	regs.ARM_r1 = arg2;
-	regs.ARM_r2 = arg3;
-	regs.ARM_r3 = arg4;
-	regs.ARM_r4 = arg5;
-	regs.ARM_r5 = arg6;
-
-	err = compel_execute_syscall(ctl, &regs, code_syscall);
-
-	*ret = regs.ARM_r0;
-	return err;
-}
-
 #define assign_reg(dst, src, e)		dst->e = (__typeof__(dst->e))((src)->ARM_##e)
 
 int save_task_regs(void *x, user_regs_struct_t *regs, user_fpregs_struct_t *fpregs)
@@ -172,24 +130,6 @@ int restore_fpu(struct rt_sigframe *sigframe, CoreEntry *core)
 	return 0;
 }
 
-void *mmap_seized(struct parasite_ctl *ctl,
-		  void *addr, size_t length, int prot,
-		  int flags, int fd, off_t offset)
-{
-	unsigned long map;
-	int err;
-
-	if (offset & ~PAGE_MASK)
-		return 0;
-
-	err = syscall_seized(ctl, __NR_mmap2, &map,
-			(unsigned long)addr, length, prot, flags, fd, offset >> 12);
-	if (err < 0 || map > kdat.task_size)
-		map = 0;
-
-	return (void *)map;
-}
-
 int restore_gpregs(struct rt_sigframe *f, UserArmRegsEntry *r)
 {
 #define CPREG1(d)       f->sig.uc.uc_mcontext.arm_##d = r->d
diff --git a/criu/arch/arm/include/asm/parasite-syscall.h b/criu/arch/arm/include/asm/parasite-syscall.h
index 7a5591ad5c7c..e420ccbdc625 100644
--- a/criu/arch/arm/include/asm/parasite-syscall.h
+++ b/criu/arch/arm/include/asm/parasite-syscall.h
@@ -9,8 +9,4 @@ struct parasite_ctl;
 
 void parasite_setup_regs(unsigned long new_ip, void *stack, user_regs_struct_t *regs);
 
-void *mmap_seized(struct parasite_ctl *ctl,
-		  void *addr, size_t length, int prot,
-		  int flags, int fd, off_t offset);
-
 #endif
diff --git a/criu/arch/arm/infect.c b/criu/arch/arm/infect.c
index d524d513026f..ec84c20aabb5 100644
--- a/criu/arch/arm/infect.c
+++ b/criu/arch/arm/infect.c
@@ -10,6 +10,23 @@
 #include "infect.h"
 #include "infect-priv.h"
 
+/*
+ * Injected syscall instruction
+ */
+const char code_syscall[] = {
+	0x00, 0x00, 0x00, 0xef,         /* SVC #0  */
+	0xf0, 0x01, 0xf0, 0xe7          /* UDF #32 */
+};
+
+static const int
+code_syscall_aligned = round_up(sizeof(code_syscall), sizeof(long));
+
+static inline __always_unused void __check_code_syscall(void)
+{
+	BUILD_BUG_ON(code_syscall_aligned != BUILTIN_SYSCALL_SIZE);
+	BUILD_BUG_ON(!is_log2(sizeof(code_syscall)));
+}
+
 #define PTRACE_GETVFPREGS 27
 int compel_get_task_regs(pid_t pid, user_regs_struct_t regs, save_regs_t save, void *arg)
 {
@@ -45,3 +62,46 @@ err:
 	return ret;
 }
 
+int compel_syscall(struct parasite_ctl *ctl, int nr, unsigned long *ret,
+		unsigned long arg1,
+		unsigned long arg2,
+		unsigned long arg3,
+		unsigned long arg4,
+		unsigned long arg5,
+		unsigned long arg6)
+{
+	user_regs_struct_t regs = ctl->orig.regs;
+	int err;
+
+	regs.ARM_r7 = (unsigned long)nr;
+	regs.ARM_r0 = arg1;
+	regs.ARM_r1 = arg2;
+	regs.ARM_r2 = arg3;
+	regs.ARM_r3 = arg4;
+	regs.ARM_r4 = arg5;
+	regs.ARM_r5 = arg6;
+
+	err = compel_execute_syscall(ctl, &regs, code_syscall);
+
+	*ret = regs.ARM_r0;
+	return err;
+}
+
+void *remote_mmap(struct parasite_ctl *ctl,
+		  void *addr, size_t length, int prot,
+		  int flags, int fd, off_t offset)
+{
+	unsigned long map;
+	int err;
+
+	if (offset & ~PAGE_MASK)
+		return 0;
+
+	err = compel_syscall(ctl, __NR_mmap2, &map,
+			(unsigned long)addr, length, prot, flags, fd, offset >> 12);
+	if (err < 0 || map > kdat.task_size)
+		map = 0;
+
+	return (void *)map;
+}
+
diff --git a/criu/arch/ppc64/crtools.c b/criu/arch/ppc64/crtools.c
index fbcdf51497ec..33c1ec416056 100644
--- a/criu/arch/ppc64/crtools.c
+++ b/criu/arch/ppc64/crtools.c
@@ -25,20 +25,6 @@
 #include "images/core.pb-c.h"
 #include "images/creds.pb-c.h"
 
-/*
- * Injected syscall instruction
- */
-const u32 code_syscall[] = {
-	0x44000002,		/* sc 		*/
-	0x0fe00000		/* twi 31,0,0	*/
-};
-
-static inline void __always_unused __check_code_syscall(void)
-{
-	BUILD_BUG_ON(sizeof(code_syscall) != BUILTIN_SYSCALL_SIZE);
-	BUILD_BUG_ON(!is_log2(sizeof(code_syscall)));
-}
-
 void parasite_setup_regs(unsigned long new_ip, void *stack, user_regs_struct_t *regs)
 {
 	/*
@@ -60,31 +46,6 @@ bool arch_can_dump_task(struct parasite_ctl *ctl)
 	return true;
 }
 
-int syscall_seized(struct parasite_ctl *ctl, int nr, unsigned long *ret,
-		unsigned long arg1,
-		unsigned long arg2,
-		unsigned long arg3,
-		unsigned long arg4,
-		unsigned long arg5,
-		unsigned long arg6)
-{
-	user_regs_struct_t regs = ctl->orig.regs;
-	int err;
-
-	regs.gpr[0] = (unsigned long)nr;
-	regs.gpr[3] = arg1;
-	regs.gpr[4] = arg2;
-	regs.gpr[5] = arg3;
-	regs.gpr[6] = arg4;
-	regs.gpr[7] = arg5;
-	regs.gpr[8] = arg6;
-
-	err = compel_execute_syscall(ctl, &regs, (char*)code_syscall);
-
-	*ret = regs.gpr[3];
-	return err;
-}
-
 static UserPpc64FpstateEntry *copy_fp_regs(uint64_t *fpregs)
 {
 	UserPpc64FpstateEntry *fpe;
@@ -565,18 +526,3 @@ int restore_gpregs(struct rt_sigframe *f, UserPpc64RegsEntry *r)
 
 	return 0;
 }
-
-void *mmap_seized(struct parasite_ctl *ctl,
-		  void *addr, size_t length, int prot,
-		  int flags, int fd, off_t offset)
-{
-	unsigned long map = 0;
-	int err;
-
-	err = syscall_seized(ctl, __NR_mmap, &map,
-			(unsigned long)addr, length, prot, flags, fd, offset);
-	if (err < 0 || (long)map < 0)
-		map = 0;
-
-	return (void *)map;
-}
diff --git a/criu/arch/ppc64/include/asm/parasite-syscall.h b/criu/arch/ppc64/include/asm/parasite-syscall.h
index 7a5591ad5c7c..e420ccbdc625 100644
--- a/criu/arch/ppc64/include/asm/parasite-syscall.h
+++ b/criu/arch/ppc64/include/asm/parasite-syscall.h
@@ -9,8 +9,4 @@ struct parasite_ctl;
 
 void parasite_setup_regs(unsigned long new_ip, void *stack, user_regs_struct_t *regs);
 
-void *mmap_seized(struct parasite_ctl *ctl,
-		  void *addr, size_t length, int prot,
-		  int flags, int fd, off_t offset);
-
 #endif
diff --git a/criu/arch/ppc64/infect.c b/criu/arch/ppc64/infect.c
index 6c9692f7c717..c76bef5e758b 100644
--- a/criu/arch/ppc64/infect.c
+++ b/criu/arch/ppc64/infect.c
@@ -19,6 +19,20 @@
 #define NT_PPC_TM_SPR   0x10c           /* TM Special Purpose Registers */
 #endif
 
+/*
+ * Injected syscall instruction
+ */
+const u32 code_syscall[] = {
+	0x44000002,		/* sc 		*/
+	0x0fe00000		/* twi 31,0,0	*/
+};
+
+static inline void __check_code_syscall(void)
+{
+	BUILD_BUG_ON(sizeof(code_syscall) != BUILTIN_SYSCALL_SIZE);
+	BUILD_BUG_ON(!is_log2(sizeof(code_syscall)));
+}
+
 /* This is the layout of the POWER7 VSX registers and the way they
  * overlap with the existing FPR and VMX registers.
  *
@@ -241,3 +255,43 @@ int compel_get_task_regs(pid_t pid, user_regs_struct_t regs, save_regs_t save, v
 
 	return save(arg, &regs, &fpregs);
 }
+
+int compel_syscall(struct parasite_ctl *ctl, int nr, unsigned long *ret,
+		unsigned long arg1,
+		unsigned long arg2,
+		unsigned long arg3,
+		unsigned long arg4,
+		unsigned long arg5,
+		unsigned long arg6)
+{
+	user_regs_struct_t regs = ctl->orig.regs;
+	int err;
+
+	regs.gpr[0] = (unsigned long)nr;
+	regs.gpr[3] = arg1;
+	regs.gpr[4] = arg2;
+	regs.gpr[5] = arg3;
+	regs.gpr[6] = arg4;
+	regs.gpr[7] = arg5;
+	regs.gpr[8] = arg6;
+
+	err = compel_execute_syscall(ctl, &regs, (char*)code_syscall);
+
+	*ret = regs.gpr[3];
+	return err;
+}
+
+void *remote_mmap(struct parasite_ctl *ctl,
+		  void *addr, size_t length, int prot,
+		  int flags, int fd, off_t offset)
+{
+	unsigned long map = 0;
+	int err;
+
+	err = compel_syscall(ctl, __NR_mmap, &map,
+			(unsigned long)addr, length, prot, flags, fd, offset);
+	if (err < 0 || (long)map < 0)
+		map = 0;
+
+	return (void *)map;
+}
diff --git a/criu/arch/x86/crtools.c b/criu/arch/x86/crtools.c
index 363a52e07c88..de3cd02f8a60 100644
--- a/criu/arch/x86/crtools.c
+++ b/criu/arch/x86/crtools.c
@@ -32,31 +32,6 @@
 #include "images/creds.pb-c.h"
 
 /*
- * Injected syscall instruction
- */
-const char code_syscall[] = {
-	0x0f, 0x05,				/* syscall    */
-	0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc	/* int 3, ... */
-};
-
-const char code_int_80[] = {
-	0xcd, 0x80,				/* int $0x80  */
-	0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc	/* int 3, ... */
-};
-
-static const int
-code_syscall_aligned = round_up(sizeof(code_syscall), sizeof(long));
-static const int
-code_int_80_aligned = round_up(sizeof(code_syscall), sizeof(long));
-
-static inline __always_unused void __check_code_syscall(void)
-{
-	BUILD_BUG_ON(code_int_80_aligned != BUILTIN_SYSCALL_SIZE);
-	BUILD_BUG_ON(code_syscall_aligned != BUILTIN_SYSCALL_SIZE);
-	BUILD_BUG_ON(!is_log2(sizeof(code_syscall)));
-}
-
-/*
  * regs must be inited when calling this function from original context
  */
 void parasite_setup_regs(unsigned long new_ip, void *stack, user_regs_struct_t *regs)
@@ -146,47 +121,6 @@ bool arch_can_dump_task(struct parasite_ctl *ctl)
 	return true;
 }
 
-int syscall_seized(struct parasite_ctl *ctl, int nr, unsigned long *ret,
-		unsigned long arg1,
-		unsigned long arg2,
-		unsigned long arg3,
-		unsigned long arg4,
-		unsigned long arg5,
-		unsigned long arg6)
-{
-	user_regs_struct_t regs = ctl->orig.regs;
-	int err;
-
-	if (user_regs_native(&regs)) {
-		user_regs_struct64 *r = &regs.native;
-
-		r->ax  = (uint64_t)nr;
-		r->di  = arg1;
-		r->si  = arg2;
-		r->dx  = arg3;
-		r->r10 = arg4;
-		r->r8  = arg5;
-		r->r9  = arg6;
-
-		err = compel_execute_syscall(ctl, &regs, code_syscall);
-	} else {
-		user_regs_struct32 *r = &regs.compat;
-
-		r->ax  = (uint32_t)nr;
-		r->bx  = arg1;
-		r->cx  = arg2;
-		r->dx  = arg3;
-		r->si  = arg4;
-		r->di  = arg5;
-		r->bp  = arg6;
-
-		err = compel_execute_syscall(ctl, &regs, code_int_80);
-	}
-
-	*ret = get_user_reg(&regs, ax);
-	return err;
-}
-
 int save_task_regs(void *x, user_regs_struct_t *regs, user_fpregs_struct_t *fpregs)
 {
 	CoreEntry *core = x;
@@ -548,29 +482,6 @@ int restore_fpu(struct rt_sigframe *sigframe, CoreEntry *core)
 	return 0;
 }
 
-void *mmap_seized(struct parasite_ctl *ctl,
-		  void *addr, size_t length, int prot,
-		  int flags, int fd, off_t offset)
-{
-	unsigned long map;
-	int err;
-	bool compat_task = !user_regs_native(&ctl->orig.regs);
-
-	err = syscall_seized(ctl, __NR(mmap, compat_task), &map,
-			(unsigned long)addr, length, prot, flags, fd, offset);
-	if (err < 0)
-		return NULL;
-
-	if (IS_ERR_VALUE(map)) {
-		if (map == -EACCES && (prot & PROT_WRITE) && (prot & PROT_EXEC))
-			pr_warn("mmap(PROT_WRITE | PROT_EXEC) failed for %d, "
-				"check selinux execmem policy\n", ctl->rpid);
-		return NULL;
-	}
-
-	return (void *)map;
-}
-
 #ifdef CONFIG_X86_64
 #define CPREG32(d)	f->compat.uc.uc_mcontext.d = r->d
 #else
diff --git a/criu/arch/x86/include/asm/parasite-syscall.h b/criu/arch/x86/include/asm/parasite-syscall.h
index cbc0442dd722..18c746f6fc59 100644
--- a/criu/arch/x86/include/asm/parasite-syscall.h
+++ b/criu/arch/x86/include/asm/parasite-syscall.h
@@ -20,8 +20,4 @@ struct parasite_ctl;
 
 void parasite_setup_regs(unsigned long new_ip, void *stack, user_regs_struct_t *regs);
 
-void *mmap_seized(struct parasite_ctl *ctl,
-		  void *addr, size_t length, int prot,
-		  int flags, int fd, off_t offset);
-
 #endif
diff --git a/criu/arch/x86/infect.c b/criu/arch/x86/infect.c
index 7c7537cb26d3..ad3ce267958d 100644
--- a/criu/arch/x86/infect.c
+++ b/criu/arch/x86/infect.c
@@ -2,6 +2,10 @@
 #include <sys/types.h>
 #include <sys/uio.h>
 #include <sys/auxv.h>
+#include <sys/mman.h>
+#include "asm/parasite-syscall.h"
+#include "uapi/std/syscall-codes.h"
+#include "err.h"
 #include "asm/fpu.h"
 #include "asm/types.h"
 #include "errno.h"
@@ -10,6 +14,31 @@
 #include "infect.h"
 #include "infect-priv.h"
 
+/*
+ * Injected syscall instruction
+ */
+const char code_syscall[] = {
+	0x0f, 0x05,				/* syscall    */
+	0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc	/* int 3, ... */
+};
+
+const char code_int_80[] = {
+	0xcd, 0x80,				/* int $0x80  */
+	0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc	/* int 3, ... */
+};
+
+static const int
+code_syscall_aligned = round_up(sizeof(code_syscall), sizeof(long));
+static const int
+code_int_80_aligned = round_up(sizeof(code_syscall), sizeof(long));
+
+static inline __always_unused void __check_code_syscall(void)
+{
+	BUILD_BUG_ON(code_int_80_aligned != BUILTIN_SYSCALL_SIZE);
+	BUILD_BUG_ON(code_syscall_aligned != BUILTIN_SYSCALL_SIZE);
+	BUILD_BUG_ON(!is_log2(sizeof(code_syscall)));
+}
+
 #define get_signed_user_reg(pregs, name)				\
 	((user_regs_native(pregs)) ? (int64_t)((pregs)->native.name) :	\
 				(int32_t)((pregs)->compat.name))
@@ -76,3 +105,67 @@ out:
 err:
 	return ret;
 }
+
+int compel_syscall(struct parasite_ctl *ctl, int nr, unsigned long *ret,
+		unsigned long arg1,
+		unsigned long arg2,
+		unsigned long arg3,
+		unsigned long arg4,
+		unsigned long arg5,
+		unsigned long arg6)
+{
+	user_regs_struct_t regs = ctl->orig.regs;
+	int err;
+
+	if (user_regs_native(&regs)) {
+		user_regs_struct64 *r = &regs.native;
+
+		r->ax  = (uint64_t)nr;
+		r->di  = arg1;
+		r->si  = arg2;
+		r->dx  = arg3;
+		r->r10 = arg4;
+		r->r8  = arg5;
+		r->r9  = arg6;
+
+		err = compel_execute_syscall(ctl, &regs, code_syscall);
+	} else {
+		user_regs_struct32 *r = &regs.compat;
+
+		r->ax  = (uint32_t)nr;
+		r->bx  = arg1;
+		r->cx  = arg2;
+		r->dx  = arg3;
+		r->si  = arg4;
+		r->di  = arg5;
+		r->bp  = arg6;
+
+		err = compel_execute_syscall(ctl, &regs, code_int_80);
+	}
+
+	*ret = get_user_reg(&regs, ax);
+	return err;
+}
+
+void *remote_mmap(struct parasite_ctl *ctl,
+		  void *addr, size_t length, int prot,
+		  int flags, int fd, off_t offset)
+{
+	unsigned long map;
+	int err;
+	bool compat_task = !user_regs_native(&ctl->orig.regs);
+
+	err = compel_syscall(ctl, __NR(mmap, compat_task), &map,
+			(unsigned long)addr, length, prot, flags, fd, offset);
+	if (err < 0)
+		return NULL;
+
+	if (IS_ERR_VALUE(map)) {
+		if (map == -EACCES && (prot & PROT_WRITE) && (prot & PROT_EXEC))
+			pr_warn("mmap(PROT_WRITE | PROT_EXEC) failed for %d, "
+				"check selinux execmem policy\n", ctl->rpid);
+		return NULL;
+	}
+
+	return (void *)map;
+}
diff --git a/criu/cr-exec.c b/criu/cr-exec.c
index 098bf96d7ced..e7b3f058f1a4 100644
--- a/criu/cr-exec.c
+++ b/criu/cr-exec.c
@@ -96,7 +96,7 @@ static int execute_syscall(struct parasite_ctl *ctl,
 	pr_info("Calling %d with %lu %lu %lu %lu %lu %lu\n", scd->nr,
 			args[0], args[1], args[2], args[3], args[4], args[5]);
 
-	err = syscall_seized(ctl, scd->nr, &ret,
+	err = compel_syscall(ctl, scd->nr, &ret,
 			args[0], args[1], args[2], args[3], args[4], args[5]);
 	if (err)
 		return err;
diff --git a/criu/include/infect-priv.h b/criu/include/infect-priv.h
index b33a635161d0..3ddd1175f754 100644
--- a/criu/include/infect-priv.h
+++ b/criu/include/infect-priv.h
@@ -40,4 +40,13 @@ int parasite_wait_ack(int sockfd, unsigned int cmd, struct ctl_msg *m);
 
 /* XXX -- remove with cr-exec.c */
 extern int compel_map_exchange(struct parasite_ctl *ctl, unsigned long size);
+extern int compel_syscall(struct parasite_ctl *ctl, int nr, unsigned long *ret,
+			  unsigned long arg1, unsigned long arg2,
+			  unsigned long arg3, unsigned long arg4,
+			  unsigned long arg5, unsigned long arg6);
+
+
+extern void *remote_mmap(struct parasite_ctl *ctl,
+		void *addr, size_t length, int prot,
+		int flags, int fd, off_t offset);
 #endif
diff --git a/criu/include/parasite-syscall.h b/criu/include/parasite-syscall.h
index 2efec72d4a03..5c4ca6de5a9b 100644
--- a/criu/include/parasite-syscall.h
+++ b/criu/include/parasite-syscall.h
@@ -64,11 +64,6 @@ extern struct parasite_tty_args *parasite_dump_tty(struct parasite_ctl *ctl, int
 extern int parasite_init_threads_seized(struct parasite_ctl *ctl, struct pstree_item *item);
 extern int parasite_fini_threads_seized(struct parasite_ctl *ctl);
 
-extern int syscall_seized(struct parasite_ctl *ctl, int nr, unsigned long *ret,
-			  unsigned long arg1, unsigned long arg2,
-			  unsigned long arg3, unsigned long arg4,
-			  unsigned long arg5, unsigned long arg6);
-
 extern bool arch_can_dump_task(struct parasite_ctl *ctl);
 
 #endif /* __CR_PARASITE_SYSCALL_H__ */
diff --git a/criu/infect.c b/criu/infect.c
index 5090413b1b6e..14fcc74767f9 100644
--- a/criu/infect.c
+++ b/criu/infect.c
@@ -603,7 +603,7 @@ static int parasite_mmap_exchange(struct parasite_ctl *ctl, unsigned long size)
 {
 	int fd;
 
-	ctl->remote_map = mmap_seized(ctl, NULL, size,
+	ctl->remote_map = remote_mmap(ctl, NULL, size,
 				      PROT_READ | PROT_WRITE | PROT_EXEC,
 				      MAP_ANONYMOUS | MAP_SHARED, -1, 0);
 	if (!ctl->remote_map) {
@@ -650,13 +650,13 @@ static int parasite_memfd_exchange(struct parasite_ctl *ctl, unsigned long size)
 		return -1;
 	}
 
-	ret = syscall_seized(ctl, __NR(memfd_create, compat_task), &sret,
+	ret = compel_syscall(ctl, __NR(memfd_create, compat_task), &sret,
 			     (unsigned long)where, 0, 0, 0, 0, 0);
 
 	if (ptrace_poke_area(pid, orig_code, where, sizeof(orig_code))) {
 		fd = (int)(long)sret;
 		if (fd >= 0)
-			syscall_seized(ctl, __NR(close, compat_task), &sret,
+			compel_syscall(ctl, __NR(close, compat_task), &sret,
 					fd, 0, 0, 0, 0, 0);
 		pr_err("Can't restore memfd args (pid: %d)\n", pid);
 		return -1;
@@ -681,7 +681,7 @@ static int parasite_memfd_exchange(struct parasite_ctl *ctl, unsigned long size)
 		goto err_cure;
 	}
 
-	ctl->remote_map = mmap_seized(ctl, NULL, size,
+	ctl->remote_map = remote_mmap(ctl, NULL, size,
 				      PROT_READ | PROT_WRITE | PROT_EXEC,
 				      MAP_FILE | MAP_SHARED, fd, 0);
 	if (!ctl->remote_map) {
@@ -697,7 +697,7 @@ static int parasite_memfd_exchange(struct parasite_ctl *ctl, unsigned long size)
 		goto err_curef;
 	}
 
-	syscall_seized(ctl, __NR(close, compat_task), &sret, fd, 0, 0, 0, 0, 0);
+	compel_syscall(ctl, __NR(close, compat_task), &sret, fd, 0, 0, 0, 0, 0);
 	close(lfd);
 
 	pr_info("Set up parasite blob using memfd\n");
@@ -706,7 +706,7 @@ static int parasite_memfd_exchange(struct parasite_ctl *ctl, unsigned long size)
 err_curef:
 	close(lfd);
 err_cure:
-	syscall_seized(ctl, __NR(close, compat_task), &sret, fd, 0, 0, 0, 0, 0);
+	compel_syscall(ctl, __NR(close, compat_task), &sret, fd, 0, 0, 0, 0, 0);
 	return -1;
 }
 
@@ -964,7 +964,7 @@ int compel_cure_remote(struct parasite_ctl *ctl)
 	} else {
 		unsigned long ret;
 
-		syscall_seized(ctl, __NR(munmap, !compel_mode_native(ctl)), &ret,
+		compel_syscall(ctl, __NR(munmap, !compel_mode_native(ctl)), &ret,
 				(unsigned long)ctl->remote_map, ctl->map_length,
 				0, 0, 0, 0);
 		if (ret) {
-- 
2.7.4



More information about the CRIU mailing list