Commit e892245d authored by Pavel Emelyanov's avatar Pavel Emelyanov

parasite: Simplify get_vma_by_ip()

We only really need this call to find where we can dive
into the victim to make a single (!) syscall. So no need
in such a complication, just have get_exec_start() call
that finds such vaddr.
Signed-off-by: 's avatarPavel Emelyanov <xemul@virtuozzo.com>
Acked-by: 's avatarCyrill Gorcunov <gorcunov@openvz.org>
parent 8d1ee5f8
...@@ -44,36 +44,28 @@ ...@@ -44,36 +44,28 @@
#define MEMFD_FNAME "CRIUMFD" #define MEMFD_FNAME "CRIUMFD"
#define MEMFD_FNAME_SZ sizeof(MEMFD_FNAME) #define MEMFD_FNAME_SZ sizeof(MEMFD_FNAME)
static int can_run_syscall(unsigned long ip, unsigned long start, static unsigned long get_exec_start(struct list_head *vma_area_list)
unsigned long end, unsigned long pad)
{
return ip >= start && ip < (end - BUILTIN_SYSCALL_SIZE - pad);
}
static int syscall_fits_vma_area(struct vma_area *vma_area, unsigned long pad)
{
return can_run_syscall((unsigned long)vma_area->e->start,
(unsigned long)vma_area->e->start,
(unsigned long)vma_area->e->end,
pad);
}
static struct vma_area *get_vma_by_ip(struct list_head *vma_area_list,
unsigned long ip,
unsigned long pad)
{ {
struct vma_area *vma_area; struct vma_area *vma_area;
list_for_each_entry(vma_area, vma_area_list, list) { list_for_each_entry(vma_area, vma_area_list, list) {
unsigned long len;
if (vma_area->e->start >= kdat.task_size) if (vma_area->e->start >= kdat.task_size)
continue; continue;
if (!(vma_area->e->prot & PROT_EXEC)) if (!(vma_area->e->prot & PROT_EXEC))
continue; continue;
if (syscall_fits_vma_area(vma_area, pad))
return vma_area; len = vma_area_len(vma_area);
if (len < BUILTIN_SYSCALL_SIZE + MEMFD_FNAME_SZ) {
pr_warn("Suspiciously short VMA @%#lx\n", (unsigned long)vma_area->e->start);
continue;
}
return vma_area->e->start;
} }
return NULL; return 0;
} }
static inline int ptrace_get_regs(int pid, user_regs_struct_t *regs) static inline int ptrace_get_regs(int pid, user_regs_struct_t *regs)
...@@ -1155,7 +1147,6 @@ err: ...@@ -1155,7 +1147,6 @@ err:
struct parasite_ctl *parasite_prep_ctl(pid_t pid, struct vm_area_list *vma_area_list) struct parasite_ctl *parasite_prep_ctl(pid_t pid, struct vm_area_list *vma_area_list)
{ {
struct parasite_ctl *ctl = NULL; struct parasite_ctl *ctl = NULL;
struct vma_area *vma_area;
if (!arch_can_dump_task(pid)) if (!arch_can_dump_task(pid))
goto err; goto err;
...@@ -1181,15 +1172,13 @@ struct parasite_ctl *parasite_prep_ctl(pid_t pid, struct vm_area_list *vma_area_ ...@@ -1181,15 +1172,13 @@ struct parasite_ctl *parasite_prep_ctl(pid_t pid, struct vm_area_list *vma_area_
return ctl; return ctl;
/* Search a place for injecting syscall */ /* Search a place for injecting syscall */
vma_area = get_vma_by_ip(&vma_area_list->h, REG_IP(ctl->orig.regs), ctl->syscall_ip = get_exec_start(&vma_area_list->h);
MEMFD_FNAME_SZ); if (!ctl->syscall_ip) {
if (!vma_area) {
pr_err("No suitable VMA found to run parasite " pr_err("No suitable VMA found to run parasite "
"bootstrap code (pid: %d)\n", pid); "bootstrap code (pid: %d)\n", pid);
goto err; goto err;
} }
ctl->syscall_ip = vma_area->e->start;
pr_debug("Parasite syscall_ip at %p\n", (void *)ctl->syscall_ip); pr_debug("Parasite syscall_ip at %p\n", (void *)ctl->syscall_ip);
return ctl; return ctl;
......
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