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)
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);
}
......
......@@ -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");
......
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