Commit 5141d323 authored by Dmitry Safonov's avatar Dmitry Safonov Committed by Andrei Vagin

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: 's avatarAndrew Vagin <avagin@virtuozzo.com>
Cc: Andrew Vagin <avagin@virtuozzo.com>
Cc: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: 's avatarDmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: 's avatarPavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: 's avatarAndrei Vagin <avagin@virtuozzo.com>
parent 8f6800db
...@@ -24,26 +24,19 @@ find_syscall_table(char *name, struct syscall_exec_desc *tbl) ...@@ -24,26 +24,19 @@ find_syscall_table(char *name, struct syscall_exec_desc *tbl)
return NULL; return NULL;
} }
int __attribute__((weak)) arch_task_compatible(pid_t pid) { return false; }
#define ARCH_HAS_FIND_SYSCALL #define ARCH_HAS_FIND_SYSCALL
/* overwrite default to search in two tables above */ /* overwrite default to search in two tables above */
#ifdef CONFIG_X86_64 #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); if (seized_native(ctl))
switch(err) {
case 0:
return find_syscall_table(name, sc_exec_table_64); return find_syscall_table(name, sc_exec_table_64);
case 1: else
return find_syscall_table(name, sc_exec_table_32); return find_syscall_table(name, sc_exec_table_32);
default: /* Error */
return NULL;
}
} }
#else #else
struct syscall_exec_desc * 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); return find_syscall_table(name, sc_exec_table_32);
} }
......
...@@ -23,7 +23,7 @@ struct syscall_exec_desc { ...@@ -23,7 +23,7 @@ struct syscall_exec_desc {
#ifndef ARCH_HAS_FIND_SYSCALL #ifndef ARCH_HAS_FIND_SYSCALL
struct syscall_exec_desc * struct syscall_exec_desc *
find_syscall(char *name, int __attribute__((unused)) pid) find_syscall(char *name, struct parasite_ctl __always_unused *ctl)
{ {
int i; int i;
...@@ -135,12 +135,6 @@ int cr_exec(int pid, char **opt) ...@@ -135,12 +135,6 @@ int cr_exec(int pid, char **opt)
goto out; 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)) if (seize_catch_task(pid))
goto out; goto out;
...@@ -178,6 +172,12 @@ int cr_exec(int pid, char **opt) ...@@ -178,6 +172,12 @@ int cr_exec(int pid, char **opt)
goto out_unseize; 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); ret = execute_syscall(ctl, si, opt + 1);
if (ret < 0) { if (ret < 0) {
pr_err("Can't execute syscall remotely\n"); pr_err("Can't execute syscall remotely\n");
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment