diff --git a/criu/arch/aarch64/include/asm/parasite-syscall.h b/criu/arch/aarch64/include/asm/parasite-syscall.h index f992bca84..7a5591ad5 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 f992bca84..7a5591ad5 100644 --- a/criu/arch/arm/include/asm/parasite-syscall.h +++ b/criu/arch/arm/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/ppc64/include/asm/parasite-syscall.h b/criu/arch/ppc64/include/asm/parasite-syscall.h index 1ac6b3b59..7a5591ad5 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 3972aa32d..49cfbed23 100644 --- a/criu/arch/x86/crtools.c +++ b/criu/arch/x86/crtools.c @@ -6,6 +6,7 @@ #include "types.h" #include "asm/processor-flags.h" +#include "asm/parasite-syscall.h" #include "asm/restorer.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" @@ -570,8 +572,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 e2c7a5abb..cbc0442dd 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 b0d5cb71d..a6e298217 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 a5ec851ea..706907e16 100644 --- a/criu/cr-restore.c +++ b/criu/cr-restore.c @@ -79,6 +79,7 @@ #include "parasite-syscall.h" #include "files-reg.h" +#include "syscall-codes.h" #include "protobuf.h" #include "images/sa.pb-c.h" @@ -1864,7 +1865,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 6004a8520..16675e895 100644 --- a/criu/include/parasite-syscall.h +++ b/criu/include/parasite-syscall.h @@ -132,7 +132,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 ba47079e1..3fa908ab4 100644 --- a/criu/parasite-syscall.c +++ b/criu/parasite-syscall.c @@ -927,7 +927,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)) @@ -962,13 +963,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; @@ -1004,8 +1023,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 @@ -1083,7 +1101,7 @@ int parasite_cure_remote(struct parasite_ctl *ctl) } else { unsigned long ret; - syscall_seized(ctl, __NR_munmap, &ret, + syscall_seized(ctl, __NR(munmap, !seized_native(ctl)), &ret, (unsigned long)ctl->remote_map, ctl->map_length, 0, 0, 0, 0); if (ret) { @@ -1137,7 +1155,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; @@ -1217,6 +1236,7 @@ static int parasite_memfd_exchange(struct parasite_ctl *ctl, unsigned long size) pid_t pid = ctl->rpid; 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; @@ -1228,13 +1248,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; } @@ -1274,7 +1295,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"); @@ -1283,7 +1304,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; }