[CRIU] [PATCHv3 08/30] syscalls: add __NR(syscall, compat) wrapper

Dmitry Safonov dsafonov at virtuozzo.com
Tue Jun 28 12:24:01 PDT 2016


Generic code uses raw syscall numbers for:
 - syscall_seized, to execute through parasite control needed syscall;
 - parasite_stop_on_syscall, to trap couple of tasks on needed syscall.

As syscall numbers may differ (and differ for x86) between native and
compatible mode, we need proper syscall wrapper here.

Cc: Cyrill Gorcunov <gorcunov at openvz.org>
Signed-off-by: Dmitry Safonov <dsafonov at virtuozzo.com>
---
 criu/arch/aarch64/include/asm/parasite-syscall.h |  1 +
 criu/arch/arm/include/asm/parasite-syscall.h     |  1 +
 criu/arch/ppc64/include/asm/parasite-syscall.h   |  2 ++
 criu/arch/x86/crtools.c                          |  5 ++-
 criu/arch/x86/include/asm/parasite-syscall.h     | 10 ++++++
 criu/arch/x86/include/asm/syscall32.h            |  8 -----
 criu/cr-restore.c                                |  4 ++-
 criu/include/parasite-syscall.h                  |  3 +-
 criu/parasite-syscall.c                          | 40 ++++++++++++++++++------
 9 files changed, 54 insertions(+), 20 deletions(-)

diff --git a/criu/arch/aarch64/include/asm/parasite-syscall.h b/criu/arch/aarch64/include/asm/parasite-syscall.h
index f992bca84adf..7a5591ad5c7c 100644
--- a/criu/arch/aarch64/include/asm/parasite-syscall.h
+++ b/criu/arch/aarch64/include/asm/parasite-syscall.h
@@ -5,6 +5,7 @@ struct parasite_ctl;
 
 #define ARCH_SI_TRAP TRAP_BRKPT
 
+#define __NR(syscall, compat)	__NR_##syscall
 
 void parasite_setup_regs(unsigned long new_ip, void *stack, user_regs_struct_t *regs);
 
diff --git a/criu/arch/arm/include/asm/parasite-syscall.h b/criu/arch/arm/include/asm/parasite-syscall.h
index 2d6b85f7cda5..a9defef14107 100644
--- a/criu/arch/arm/include/asm/parasite-syscall.h
+++ b/criu/arch/arm/include/asm/parasite-syscall.h
@@ -4,6 +4,7 @@
 
 #define ARCH_SI_TRAP TRAP_BRKPT
 
+#define __NR(syscall, compat)	__NR_##syscall
 
 void parasite_setup_regs(unsigned long new_ip, void *stack, user_regs_struct_t *regs);
 
diff --git a/criu/arch/ppc64/include/asm/parasite-syscall.h b/criu/arch/ppc64/include/asm/parasite-syscall.h
index 1ac6b3b596b7..7a5591ad5c7c 100644
--- a/criu/arch/ppc64/include/asm/parasite-syscall.h
+++ b/criu/arch/ppc64/include/asm/parasite-syscall.h
@@ -5,6 +5,8 @@ struct parasite_ctl;
 
 #define ARCH_SI_TRAP TRAP_BRKPT
 
+#define __NR(syscall, compat)	__NR_##syscall
+
 void parasite_setup_regs(unsigned long new_ip, void *stack, user_regs_struct_t *regs);
 
 void *mmap_seized(struct parasite_ctl *ctl,
diff --git a/criu/arch/x86/crtools.c b/criu/arch/x86/crtools.c
index eb5b9592125d..733d13484692 100644
--- a/criu/arch/x86/crtools.c
+++ b/criu/arch/x86/crtools.c
@@ -5,6 +5,7 @@
 #include <sys/mman.h>
 
 #include "asm/processor-flags.h"
+#include "asm/parasite-syscall.h"
 #include "asm/restorer.h"
 #include "asm/types.h"
 #include "asm/fpu.h"
@@ -18,6 +19,7 @@
 #include "util.h"
 #include "cpu.h"
 #include "errno.h"
+#include "syscall-codes.h"
 
 #include "protobuf.h"
 #include "images/core.pb-c.h"
@@ -556,8 +558,9 @@ void *mmap_seized(struct parasite_ctl *ctl,
 {
 	unsigned long map;
 	int err;
+	bool compat_task = !user_regs_native(&ctl->orig.regs);
 
-	err = syscall_seized(ctl, __NR_mmap, &map,
+	err = syscall_seized(ctl, __NR(mmap, compat_task), &map,
 			(unsigned long)addr, length, prot, flags, fd, offset);
 	if (err < 0)
 		return NULL;
diff --git a/criu/arch/x86/include/asm/parasite-syscall.h b/criu/arch/x86/include/asm/parasite-syscall.h
index e2c7a5abb95f..cbc0442dd722 100644
--- a/criu/arch/x86/include/asm/parasite-syscall.h
+++ b/criu/arch/x86/include/asm/parasite-syscall.h
@@ -7,6 +7,16 @@ struct parasite_ctl;
 
 #define ARCH_SI_TRAP SI_KERNEL
 
+#define __NR(syscall, compat)	((compat) ? __NR32_##syscall : __NR_##syscall)
+
+/*
+ * For x86_32 __NR_mmap inside the kernel represents old_mmap system
+ * call, but since we didn't use it yet lets go further and simply
+ * define own alias for __NR_mmap2 which would allow us to unify code
+ * between 32 and 64 bits version.
+ */
+#define __NR32_mmap __NR32_mmap2
+
 
 void parasite_setup_regs(unsigned long new_ip, void *stack, user_regs_struct_t *regs);
 
diff --git a/criu/arch/x86/include/asm/syscall32.h b/criu/arch/x86/include/asm/syscall32.h
index b0d5cb71d3a5..a6e298217d64 100644
--- a/criu/arch/x86/include/asm/syscall32.h
+++ b/criu/arch/x86/include/asm/syscall32.h
@@ -14,12 +14,4 @@ extern long sys_getsockopt(int sockfd, int level, int optname, const void *optva
 extern long sys_shmat(int shmid, void *shmaddr, int shmflag);
 extern long sys_pread(unsigned int fd, char *ubuf, u32 count, u64 pos);
 
-/*
- * For x86_32 __NR_mmap inside the kernel represents old_mmap system
- * call, but since we didn't use it yet lets go further and simply
- * define own alias for __NR_mmap2 which would allow us to unify code
- * between 32 and 64 bits version.
- */
-#define __NR_mmap __NR_mmap2
-
 #endif /* __CR_SYSCALL32_H__ */
diff --git a/criu/cr-restore.c b/criu/cr-restore.c
index 979c385baf87..874ff3484713 100644
--- a/criu/cr-restore.c
+++ b/criu/cr-restore.c
@@ -79,6 +79,7 @@
 #include "sk-queue.h"
 #include "syscall-types.h"
 #include "parasite-syscall.h"
+#include "syscall-codes.h"
 
 #include "protobuf.h"
 #include "images/sa.pb-c.h"
@@ -91,6 +92,7 @@
 #include "asm/restore.h"
 #include "asm/atomic.h"
 #include "asm/bitops.h"
+#include "asm/parasite-syscall.h"
 
 #include "cr-errno.h"
 
@@ -1823,7 +1825,7 @@ static int restore_root_task(struct pstree_item *init)
 
 	if (ret == 0)
 		ret = parasite_stop_on_syscall(task_entries->nr_threads,
-						__NR_rt_sigreturn, flag);
+			__NR(rt_sigreturn, 0), __NR(rt_sigreturn, 1), flag);
 
 	if (clear_breakpoints())
 		pr_err("Unable to flush breakpoints\n");
diff --git a/criu/include/parasite-syscall.h b/criu/include/parasite-syscall.h
index 15a13a6de853..ae5a2c0ed9e6 100644
--- a/criu/include/parasite-syscall.h
+++ b/criu/include/parasite-syscall.h
@@ -135,7 +135,8 @@ enum trace_flags {
 };
 
 extern int parasite_stop_daemon(struct parasite_ctl *ctl);
-extern int parasite_stop_on_syscall(int tasks, int sys_nr, enum trace_flags trace);
+extern int parasite_stop_on_syscall(int tasks, int sys_nr,
+		int sys_nr_compat, enum trace_flags trace);
 extern int parasite_unmap(struct parasite_ctl *ctl, unsigned long addr);
 extern int ptrace_stop_pie(pid_t pid, void *addr, enum trace_flags *tf);
 
diff --git a/criu/parasite-syscall.c b/criu/parasite-syscall.c
index c2467dcfaf22..bce494433541 100644
--- a/criu/parasite-syscall.c
+++ b/criu/parasite-syscall.c
@@ -29,6 +29,7 @@
 #include "proc_parse.h"
 #include "aio.h"
 #include "fault-injection.h"
+#include "syscall-codes.h"
 
 #include <string.h>
 #include <stdlib.h>
@@ -920,7 +921,8 @@ static int parasite_fini_seized(struct parasite_ctl *ctl)
 	if (ret < 0)
 		return ret;
 
-	if (parasite_stop_on_syscall(1, __NR_rt_sigreturn, flag))
+	if (parasite_stop_on_syscall(1, __NR(rt_sigreturn, 0),
+				__NR(rt_sigreturn, 1), flag))
 		return -1;
 
 	if (ptrace_flush_breakpoints(pid))
@@ -955,13 +957,31 @@ static bool task_is_trapped(int status, pid_t pid)
 	return false;
 }
 
+static inline int is_required_syscall(user_regs_struct_t regs, pid_t pid,
+		const int sys_nr, const int sys_nr_compat)
+{
+	const char *mode = user_regs_native(&regs) ? "native" : "compat";
+	int req_sysnr = user_regs_native(&regs) ? sys_nr : sys_nr_compat;
+
+	pr_debug("%d (%s) is going to execute the syscall %lu, required is %d\n",
+		pid, mode, REG_SYSCALL_NR(regs), req_sysnr);
+	if (user_regs_native(&regs) && (REG_SYSCALL_NR(regs) == sys_nr))
+		return true;
+	if (!user_regs_native(&regs) && (REG_SYSCALL_NR(regs) == sys_nr_compat))
+		return true;
+
+	return false;
+}
 /*
  * Trap tasks on the exit from the specified syscall
  *
  * tasks - number of processes, which should be trapped
  * sys_nr - the required syscall number
+ * sys_nr_compat - the required compatible syscall number
  */
-int parasite_stop_on_syscall(int tasks, const int sys_nr, enum trace_flags trace)
+int parasite_stop_on_syscall(int tasks,
+	const int sys_nr, const int sys_nr_compat,
+	enum trace_flags trace)
 {
 	user_regs_struct_t regs;
 	int status, ret;
@@ -997,8 +1017,7 @@ int parasite_stop_on_syscall(int tasks, const int sys_nr, enum trace_flags trace
 			return -1;
 		}
 
-		pr_debug("%d is going to execute the syscall %lu\n", pid, REG_SYSCALL_NR(regs));
-		if (REG_SYSCALL_NR(regs) == sys_nr) {
+		if (is_required_syscall(regs, pid, sys_nr, sys_nr_compat)) {
 			/*
 			 * The process is going to execute the required syscall,
 			 * the next stop will be on the exit from this syscall
@@ -1117,7 +1136,8 @@ int parasite_unmap(struct parasite_ctl *ctl, unsigned long addr)
 	if (ret)
 		goto err;
 
-	ret = parasite_stop_on_syscall(1, __NR_munmap, TRACE_ENTER);
+	ret = parasite_stop_on_syscall(1, __NR(munmap, 0),
+			__NR(munmap, 1), TRACE_ENTER);
 
 	if (restore_thread_ctx(pid, &ctl->orig))
 		ret = -1;
@@ -1213,6 +1233,7 @@ static int parasite_memfd_exchange(struct parasite_ctl *ctl, unsigned long size)
 	pid_t pid = ctl->pid.real;
 	unsigned long sret = -ENOSYS;
 	int ret, fd, lfd;
+	bool __maybe_unused compat_task = !user_regs_native(&ctl->orig.regs);
 
 	if (fault_injected(FI_NO_MEMFD))
 		return 1;
@@ -1224,13 +1245,14 @@ static int parasite_memfd_exchange(struct parasite_ctl *ctl, unsigned long size)
 		return -1;
 	}
 
-	ret = syscall_seized(ctl, __NR_memfd_create, &sret,
+	ret = syscall_seized(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, &sret, fd, 0, 0, 0, 0, 0);
+			syscall_seized(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;
 	}
@@ -1270,7 +1292,7 @@ static int parasite_memfd_exchange(struct parasite_ctl *ctl, unsigned long size)
 		goto err_curef;
 	}
 
-	syscall_seized(ctl, __NR_close, &sret, fd, 0, 0, 0, 0, 0);
+	syscall_seized(ctl, __NR(close, compat_task), &sret, fd, 0, 0, 0, 0, 0);
 	close(lfd);
 
 	pr_info("Set up parasite blob using memfd\n");
@@ -1279,7 +1301,7 @@ static int parasite_memfd_exchange(struct parasite_ctl *ctl, unsigned long size)
 err_curef:
 	close(lfd);
 err_cure:
-	syscall_seized(ctl, __NR_close, &sret, fd, 0, 0, 0, 0, 0);
+	syscall_seized(ctl, __NR(close, compat_task), &sret, fd, 0, 0, 0, 0, 0);
 	return -1;
 }
 #else
-- 
2.9.0



More information about the CRIU mailing list