Commit 250d4e91 authored by Pavel Emelyanov's avatar Pavel Emelyanov Committed by Cyrill Gorcunov

parasite: Remove extra on-stack regsets

In fact all we need for parasitic syscall is -- original regs and some
regs with syscall args to work on. The former one is obtained in the
infect/cure code and the latter one is located (and copied from orig)
nearby.

That said, we can simplify all the regs passing-down code by removing
intermediate instances and utilizing the top-level reg-s for this.
Signed-off-by: 's avatarPavel Emelyanov <xemul@parallels.com>
Signed-off-by: 's avatarCyrill Gorcunov <gorcunov@openvz.org>
parent cf662edc
...@@ -47,9 +47,8 @@ int can_run_syscall(unsigned long ip, unsigned long start, unsigned long end) ...@@ -47,9 +47,8 @@ int can_run_syscall(unsigned long ip, unsigned long start, unsigned long end)
return ip >= start && ip < (end - code_syscall_size); return ip >= start && ip < (end - code_syscall_size);
} }
static int syscall_seized(pid_t pid, user_regs_struct_t *params) static int syscall_seized(pid_t pid, user_regs_struct_t *regs)
{ {
user_regs_struct_t regs_orig, regs;
unsigned long start_ip; unsigned long start_ip;
char saved[sizeof(code_syscall)]; char saved[sizeof(code_syscall)];
siginfo_t siginfo; siginfo_t siginfo;
...@@ -59,26 +58,14 @@ static int syscall_seized(pid_t pid, user_regs_struct_t *params) ...@@ -59,26 +58,14 @@ static int syscall_seized(pid_t pid, user_regs_struct_t *params)
BUILD_BUG_ON(sizeof(code_syscall) != BUILTIN_SYSCALL_SIZE); BUILD_BUG_ON(sizeof(code_syscall) != BUILTIN_SYSCALL_SIZE);
BUILD_BUG_ON(!is_log2(sizeof(code_syscall))); BUILD_BUG_ON(!is_log2(sizeof(code_syscall)));
start_ip = (unsigned long)params->ip; start_ip = (unsigned long)regs->ip;
jerr(ptrace_peek_area(pid, (void *)saved, (void *)start_ip, code_syscall_size), err); jerr(ptrace_peek_area(pid, (void *)saved, (void *)start_ip, code_syscall_size), err);
jerr(ptrace_poke_area(pid, (void *)code_syscall, (void *)start_ip, code_syscall_size), err); jerr(ptrace_poke_area(pid, (void *)code_syscall, (void *)start_ip, code_syscall_size), err);
regs->orig_ax = -1; /* avoid end-of-syscall processing */
again: again:
jerr(ptrace(PTRACE_GETREGS, pid, NULL, &regs), err); jerr(ptrace(PTRACE_SETREGS, pid, NULL, regs), err_restore);
regs_orig = regs;
regs.ip = start_ip;
regs.ax = params->ax;
regs.di = params->di;
regs.si = params->si;
regs.dx = params->dx;
regs.r10 = params->r10;
regs.r8 = params->r8;
regs.r9 = params->r9;
regs.orig_ax = -1; /* avoid end-of-syscall processing */
jerr(ptrace(PTRACE_SETREGS, pid, NULL, &regs), err_restore);
/* /*
* Most ideas are taken from Tejun Heo's parasite thread * Most ideas are taken from Tejun Heo's parasite thread
...@@ -100,7 +87,6 @@ retry_signal: ...@@ -100,7 +87,6 @@ retry_signal:
/* pr_debug("** delivering signal %d si_code=%d\n", /* pr_debug("** delivering signal %d si_code=%d\n",
siginfo.si_signo, siginfo.si_code); */ siginfo.si_signo, siginfo.si_code); */
/* FIXME: jerr(siginfo.si_code > 0, err_restore_full); */ /* FIXME: jerr(siginfo.si_code > 0, err_restore_full); */
jerr(ptrace(PTRACE_SETREGS, pid, NULL, (void *)&regs_orig), err_restore_full);
jerr(ptrace(PTRACE_INTERRUPT, pid, NULL, NULL), err_restore_full); jerr(ptrace(PTRACE_INTERRUPT, pid, NULL, NULL), err_restore_full);
jerr(ptrace(PTRACE_CONT, pid, NULL, (void *)(unsigned long)siginfo.si_signo), err_restore_full); jerr(ptrace(PTRACE_CONT, pid, NULL, (void *)(unsigned long)siginfo.si_signo), err_restore_full);
...@@ -128,16 +114,11 @@ retry_signal: ...@@ -128,16 +114,11 @@ retry_signal:
jerr((siginfo.si_code >> 8 != PTRACE_EVENT_STOP), err_restore_full); jerr((siginfo.si_code >> 8 != PTRACE_EVENT_STOP), err_restore_full);
jerr(ptrace(PTRACE_GETREGS, pid, NULL, params), err_restore_full); jerr(ptrace(PTRACE_GETREGS, pid, NULL, regs), err_restore_full);
ret = 0; ret = 0;
err_restore_full: err_restore_full:
if (ptrace(PTRACE_SETREGS, pid, NULL, &regs_orig)) {
pr_panic("Can't restore registers (pid: %d)\n", pid);
ret = -1;
}
err_restore: err_restore:
if (ptrace_poke_area(pid, (void *)saved, (void *)start_ip, code_syscall_size)) { if (ptrace_poke_area(pid, (void *)saved, (void *)start_ip, code_syscall_size)) {
pr_panic("Crap... Can't restore data (pid: %d)\n", pid); pr_panic("Crap... Can't restore data (pid: %d)\n", pid);
...@@ -151,22 +132,21 @@ static void *mmap_seized(pid_t pid, user_regs_struct_t *regs, ...@@ -151,22 +132,21 @@ static void *mmap_seized(pid_t pid, user_regs_struct_t *regs,
void *addr, size_t length, int prot, void *addr, size_t length, int prot,
int flags, int fd, off_t offset) int flags, int fd, off_t offset)
{ {
user_regs_struct_t params = *regs;
void *mmaped = NULL; void *mmaped = NULL;
int ret; int ret;
params.ax = (unsigned long)__NR_mmap; /* mmap */ regs->ax = (unsigned long)__NR_mmap; /* mmap */
params.di = (unsigned long)addr; /* @addr */ regs->di = (unsigned long)addr; /* @addr */
params.si = (unsigned long)length; /* @length */ regs->si = (unsigned long)length; /* @length */
params.dx = (unsigned long)prot; /* @prot */ regs->dx = (unsigned long)prot; /* @prot */
params.r10 = (unsigned long)flags; /* @flags */ regs->r10 = (unsigned long)flags; /* @flags */
params.r8 = (unsigned long)fd; /* @fd */ regs->r8 = (unsigned long)fd; /* @fd */
params.r9 = (unsigned long)offset; /* @offset */ regs->r9 = (unsigned long)offset; /* @offset */
ret = syscall_seized(pid, &params); ret = syscall_seized(pid, regs);
if (ret) if (ret)
goto err; goto err;
mmaped = (void *)params.ax; mmaped = (void *)regs->ax;
/* error code from the kernel space */ /* error code from the kernel space */
if ((long)mmaped < 0) if ((long)mmaped < 0)
...@@ -178,16 +158,15 @@ err: ...@@ -178,16 +158,15 @@ err:
static int munmap_seized(pid_t pid, user_regs_struct_t *regs, static int munmap_seized(pid_t pid, user_regs_struct_t *regs,
void *addr, size_t length) void *addr, size_t length)
{ {
user_regs_struct_t params = *regs;
int ret; int ret;
params.ax = (unsigned long)__NR_munmap; /* mmap */ regs->ax = (unsigned long)__NR_munmap; /* mmap */
params.di = (unsigned long)addr; /* @addr */ regs->di = (unsigned long)addr; /* @addr */
params.si = (unsigned long)length; /* @length */ regs->si = (unsigned long)length; /* @length */
ret = syscall_seized(pid, &params); ret = syscall_seized(pid, regs);
if (!ret) if (!ret)
ret = (int)params.ax; ret = (int)regs->ax;
return ret; return ret;
} }
......
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