From 5141d3238abd22bc98bd2b3117ebbed16614c60f Mon Sep 17 00:00:00 2001 From: Dmitry Safonov Date: Thu, 7 Jul 2016 16:36:16 +0300 Subject: [PATCH] cr-exec: check syscall's number right before injecting it So, I made a mistake in find_syscall: it can't use arch_task_compatible to find out in which mode the application is (native/compat). The reason is that arch_task_compatible uses PTRACE_GETREGSET. And at the moment of find_syscall we haven't yet seized the task. In this patch I move syscall's number check right before injecting a syscall, where we have parasite_ctl with all needed information about task's mode. This makes error-path for wrong syscall number longer and subtler (includes curing now), but I think it's a corner-case, so as it makes error-less path to execute_syscall shorter and without additional ptrace syscalls, it's better. Reported-by: Andrew Vagin Cc: Andrew Vagin Cc: Cyrill Gorcunov Signed-off-by: Dmitry Safonov Signed-off-by: Pavel Emelyanov Signed-off-by: Andrei Vagin --- criu/arch/x86/sys-exec-tbl.c | 19 ++++++------------- criu/cr-exec.c | 14 +++++++------- 2 files changed, 13 insertions(+), 20 deletions(-) diff --git a/criu/arch/x86/sys-exec-tbl.c b/criu/arch/x86/sys-exec-tbl.c index b7f95b98e..ca45ef0d3 100644 --- a/criu/arch/x86/sys-exec-tbl.c +++ b/criu/arch/x86/sys-exec-tbl.c @@ -24,26 +24,19 @@ find_syscall_table(char *name, struct syscall_exec_desc *tbl) return NULL; } -int __attribute__((weak)) arch_task_compatible(pid_t pid) { return false; } #define ARCH_HAS_FIND_SYSCALL /* overwrite default to search in two tables above */ #ifdef CONFIG_X86_64 -struct syscall_exec_desc * find_syscall(char *name, int pid) +struct syscall_exec_desc * find_syscall(char *name, struct parasite_ctl *ctl) { - int err = arch_task_compatible(pid); - - switch(err) { - case 0: - return find_syscall_table(name, sc_exec_table_64); - case 1: - return find_syscall_table(name, sc_exec_table_32); - default: /* Error */ - return NULL; - } + if (seized_native(ctl)) + return find_syscall_table(name, sc_exec_table_64); + else + return find_syscall_table(name, sc_exec_table_32); } #else struct syscall_exec_desc * -find_syscall(char *name, __attribute__((unused)) int pid) +find_syscall(char *name, __always_unused struct parasite_ctl *ctl) { return find_syscall_table(name, sc_exec_table_32); } diff --git a/criu/cr-exec.c b/criu/cr-exec.c index 618a73c1e..356e206d5 100644 --- a/criu/cr-exec.c +++ b/criu/cr-exec.c @@ -23,7 +23,7 @@ struct syscall_exec_desc { #ifndef ARCH_HAS_FIND_SYSCALL struct syscall_exec_desc * -find_syscall(char *name, int __attribute__((unused)) pid) +find_syscall(char *name, struct parasite_ctl __always_unused *ctl) { int i; @@ -135,12 +135,6 @@ int cr_exec(int pid, char **opt) goto out; } - si = find_syscall(sys_name, pid); - if (!si) { - pr_err("Unknown syscall [%s]\n", sys_name); - goto out; - } - if (seize_catch_task(pid)) goto out; @@ -178,6 +172,12 @@ int cr_exec(int pid, char **opt) goto out_unseize; } + si = find_syscall(sys_name, ctl); + if (!si) { + pr_err("Unknown syscall [%s]\n", sys_name); + goto out_cure; + } + ret = execute_syscall(ctl, si, opt + 1); if (ret < 0) { pr_err("Can't execute syscall remotely\n");