[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(®s) ? "native" : "compat";
+ int req_sysnr = user_regs_native(®s) ? 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(®s) && (REG_SYSCALL_NR(regs) == sys_nr))
+ return true;
+ if (!user_regs_native(®s) && (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