diff --git a/arch/arm/crtools.c b/arch/arm/crtools.c index c1ee5dc1d..8428e15b8 100644 --- a/arch/arm/crtools.c +++ b/arch/arm/crtools.c @@ -47,6 +47,13 @@ void parasite_setup_regs(unsigned long new_ip, user_regs_struct_t *regs) regs->ARM_cpsr &= PSR_f | PSR_s | PSR_x | PSR_T_BIT | MODE32_BIT; } +int task_in_compat_mode(pid_t pid) +{ + /* + * TODO: Add proper check here + */ + return 0; +} int syscall_seized(struct parasite_ctl *ctl, int nr, unsigned long *ret, unsigned long arg1, diff --git a/arch/x86/crtools.c b/arch/x86/crtools.c index 605979e7b..dcb8f55f0 100644 --- a/arch/x86/crtools.c +++ b/arch/x86/crtools.c @@ -45,6 +45,28 @@ void parasite_setup_regs(unsigned long new_ip, user_regs_struct_t *regs) regs->flags &= ~(X86_EFLAGS_TF | X86_EFLAGS_DF | X86_EFLAGS_IF); } +int task_in_compat_mode(pid_t pid) +{ + unsigned long cs, ds; + + errno = 0; + cs = ptrace(PTRACE_PEEKUSER, pid, offsetof(user_regs_struct_t, cs), 0); + if (errno != 0) { + perror("Can't get CS register"); + return -1; + } + + errno = 0; + ds = ptrace(PTRACE_PEEKUSER, pid, offsetof(user_regs_struct_t, ds), 0); + if (errno != 0) { + perror("Can't get DS register"); + return -1; + } + + /* It's x86-32 or x32 */ + return cs != 0x33 || ds == 0x2b; +} + int syscall_seized(struct parasite_ctl *ctl, int nr, unsigned long *ret, unsigned long arg1, unsigned long arg2, diff --git a/include/parasite-syscall.h b/include/parasite-syscall.h index 0c222fb54..2f32d03c6 100644 --- a/include/parasite-syscall.h +++ b/include/parasite-syscall.h @@ -71,5 +71,6 @@ int syscall_seized(struct parasite_ctl *ctl, int nr, unsigned long *ret, unsigned long arg6); extern int __parasite_execute(struct parasite_ctl *ctl, pid_t pid, user_regs_struct_t *regs); +extern int task_in_compat_mode(pid_t pid); #endif /* __CR_PARASITE_SYSCALL_H__ */ diff --git a/parasite-syscall.c b/parasite-syscall.c index 0941c3912..c86307f8a 100644 --- a/parasite-syscall.c +++ b/parasite-syscall.c @@ -713,6 +713,11 @@ struct parasite_ctl *parasite_prep_ctl(pid_t pid, struct list_head *vma_area_lis struct parasite_ctl *ctl = NULL; struct vma_area *vma_area; + if (task_in_compat_mode(pid)) { + pr_err("Can't checkpoint task running in compat mode\n"); + goto err; + } + /* * Control block early setup. */