[CRIU] [PATCHv3 2/4] cr-exec: check syscall's number right before injecting it

Dmitry Safonov dsafonov at virtuozzo.com
Thu Jul 7 04:51:54 PDT 2016


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 <avagin at virtuozzo.com>
Cc: Andrew Vagin <avagin at virtuozzo.com>
Cc: Cyrill Gorcunov <gorcunov at openvz.org>
Signed-off-by: Dmitry Safonov <dsafonov at virtuozzo.com>
---
 criu/arch/x86/sys-exec-tbl.c | 19 ++++++-------------
 criu/cr-exec.c               | 15 ++++++++-------
 2 files changed, 14 insertions(+), 20 deletions(-)

diff --git a/criu/arch/x86/sys-exec-tbl.c b/criu/arch/x86/sys-exec-tbl.c
index b7f95b98e5a6..27e567063312 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, __attribute__((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 a4c07e2f05a5..e8177388686b 100644
--- a/criu/cr-exec.c
+++ b/criu/cr-exec.c
@@ -19,7 +19,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 __attribute__((unused)) *ctl)
 {
 	int i;
 
@@ -125,12 +125,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;
 
@@ -159,10 +153,17 @@ 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");
 
+out_cure:
 	parasite_cure_seized(ctl);
 out_unseize:
 	unseize_task(pid, prev_state, prev_state);
-- 
2.9.0



More information about the CRIU mailing list