Commit 354ab03a authored by Pavel Emelyanov's avatar Pavel Emelyanov Committed by Cyrill Gorcunov

parasite: Enlighten parasite blob injection

I don't like that we poke the parasite into remote space with 4k calls
to ptrace. Now we have the /proc/pid/map_files/ dir which helps us sharing
a mapping with some other process.

Use this -- map the remote area for parasite locally and put the parasite
blob into it with simple memcpy.
Signed-off-by: 's avatarPavel Emelyanov <xemul@parallels.com>
Signed-off-by: 's avatarCyrill Gorcunov <gorcunov@openvz.org>
parent 2b1a58b3
...@@ -1195,7 +1195,7 @@ static int dump_one_task(struct pstree_item *item, struct cr_fdset *cr_fdset) ...@@ -1195,7 +1195,7 @@ static int dump_one_task(struct pstree_item *item, struct cr_fdset *cr_fdset)
goto err; goto err;
} }
parasite_ctl = parasite_infect_seized(pid, &vma_area_list); parasite_ctl = parasite_infect_seized(pid, pid_dir, &vma_area_list);
if (!parasite_ctl) { if (!parasite_ctl) {
pr_err("Can't infect (pid: %d) with parasite\n", pid); pr_err("Can't infect (pid: %d) with parasite\n", pid);
goto err; goto err;
......
...@@ -14,7 +14,9 @@ ...@@ -14,7 +14,9 @@
/* parasite control block */ /* parasite control block */
struct parasite_ctl { struct parasite_ctl {
pid_t pid; /* process pid where we live in */ pid_t pid; /* process pid where we live in */
struct vma_area vma_area; /* our space we host */ void * remote_map;
void * local_map;
unsigned long map_length;
unsigned long parasite_ip; /* service routine start ip */ unsigned long parasite_ip; /* service routine start ip */
unsigned long addr_cmd; /* addr for command */ unsigned long addr_cmd; /* addr for command */
unsigned long addr_args; /* address for arguments */ unsigned long addr_args; /* address for arguments */
...@@ -30,7 +32,7 @@ extern int parasite_dump_itimers_seized(struct parasite_ctl *ctl, struct cr_fdse ...@@ -30,7 +32,7 @@ extern int parasite_dump_itimers_seized(struct parasite_ctl *ctl, struct cr_fdse
struct parasite_dump_misc; struct parasite_dump_misc;
extern int parasite_dump_misc_seized(struct parasite_ctl *ctl, struct parasite_dump_misc *); extern int parasite_dump_misc_seized(struct parasite_ctl *ctl, struct parasite_dump_misc *);
extern struct parasite_ctl *parasite_infect_seized(pid_t pid, struct list_head *vma_area_list); extern struct parasite_ctl *parasite_infect_seized(pid_t pid, int pid_dir, struct list_head *vma_area_list);
extern int parasite_cure_seized(struct parasite_ctl *ctl, struct list_head *vma_area_list); extern int parasite_cure_seized(struct parasite_ctl *ctl, struct list_head *vma_area_list);
#endif /* PARASITE_SYSCALL_H_ */ #endif /* PARASITE_SYSCALL_H_ */
...@@ -527,9 +527,7 @@ int parasite_cure_seized(struct parasite_ctl *ctl, struct list_head *vma_area_li ...@@ -527,9 +527,7 @@ int parasite_cure_seized(struct parasite_ctl *ctl, struct list_head *vma_area_li
regs.ip = vma_area->vma.start; regs.ip = vma_area->vma.start;
ret = munmap_seized(ctl->pid, &regs, ret = munmap_seized(ctl->pid, &regs, ctl->remote_map, ctl->map_length);
(void *)ctl->vma_area.vma.start,
(size_t)vma_entry_len(&ctl->vma_area.vma));
if (ret) if (ret)
pr_err("munmap_seized failed (pid: %d)\n", ctl->pid); pr_err("munmap_seized failed (pid: %d)\n", ctl->pid);
...@@ -543,14 +541,14 @@ err: ...@@ -543,14 +541,14 @@ err:
return ret; return ret;
} }
struct parasite_ctl *parasite_infect_seized(pid_t pid, struct list_head *vma_area_list) struct parasite_ctl *parasite_infect_seized(pid_t pid, int pid_dir, struct list_head *vma_area_list)
{ {
parasite_status_t args = { }; parasite_status_t args = { };
user_regs_struct_t regs, regs_orig; user_regs_struct_t regs, regs_orig;
struct parasite_ctl *ctl = NULL; struct parasite_ctl *ctl = NULL;
struct vma_area *vma_area; struct vma_area *vma_area;
void *mmaped; char fname[128];
int ret; int ret, fd;
ctl = xzalloc(sizeof(*ctl)); ctl = xzalloc(sizeof(*ctl));
if (!ctl) { if (!ctl) {
...@@ -572,37 +570,43 @@ struct parasite_ctl *parasite_infect_seized(pid_t pid, struct list_head *vma_are ...@@ -572,37 +570,43 @@ struct parasite_ctl *parasite_infect_seized(pid_t pid, struct list_head *vma_are
} }
regs_orig = regs; regs_orig = regs;
/*
* Prepare for in-process syscall.
*/
ctl->vma_area.vma.prot = PROT_READ | PROT_WRITE | PROT_EXEC;
ctl->vma_area.vma.flags = MAP_PRIVATE | MAP_ANONYMOUS;
regs.ip = vma_area->vma.start; regs.ip = vma_area->vma.start;
mmaped = mmap_seized(pid, &regs, NULL, (size_t)parasite_size, ctl->remote_map = mmap_seized(pid, &regs, NULL, (size_t)parasite_size,
(int)ctl->vma_area.vma.prot, PROT_READ | PROT_WRITE | PROT_EXEC,
(int)ctl->vma_area.vma.flags, MAP_ANONYMOUS | MAP_SHARED, -1, 0);
(int)-1, (off_t)0);
if (!mmaped || (long)mmaped < 0) { if (!ctl->remote_map || (long)ctl->remote_map < 0) {
pr_err("Can't allocate memory for parasite blob (pid: %d)\n", pid); pr_err("Can't allocate memory for parasite blob (pid: %d)\n", pid);
goto err_restore_regs; goto err_restore_regs;
} }
ctl->parasite_ip = PARASITE_HEAD_ADDR((unsigned long)mmaped); ctl->map_length = round_up(parasite_size, PAGE_SIZE);
ctl->addr_cmd = PARASITE_CMD_ADDR((unsigned long)mmaped);
ctl->addr_args = PARASITE_ARGS_ADDR((unsigned long)mmaped);
ctl->vma_area.vma.start = (u64)mmaped; ctl->parasite_ip = PARASITE_HEAD_ADDR((unsigned long)ctl->remote_map);
ctl->vma_area.vma.end = (u64)(mmaped + parasite_size); ctl->addr_cmd = PARASITE_CMD_ADDR((unsigned long)ctl->remote_map);
ctl->addr_args = PARASITE_ARGS_ADDR((unsigned long)ctl->remote_map);
if (ptrace_poke_area(pid, parasite_blob, mmaped, parasite_size)) { snprintf(fname, sizeof(fname), "map_files/%p-%p",
pr_err("Can't inject parasite blob (pid: %d)\n", pid); ctl->remote_map, ctl->remote_map + ctl->map_length);
fd = openat(pid_dir, fname, O_RDWR);
if (fd < 0) {
pr_perror("Can't open remote parasite map");
goto err_munmap_restore; goto err_munmap_restore;
} }
ctl->local_map = mmap(NULL, parasite_size, PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_FILE, fd, 0);
close(fd);
if (ctl->local_map == MAP_FAILED) {
pr_perror("Can't map remote parasite map");
goto err_munmap_restore;
}
pr_info("Putting parasite blob into %p->%p\n", ctl->local_map, ctl->remote_map);
memcpy(ctl->local_map, parasite_blob, parasite_size);
jerr(ptrace(PTRACE_SETREGS, pid, NULL, &regs_orig), err_munmap_restore); jerr(ptrace(PTRACE_SETREGS, pid, NULL, &regs_orig), err_munmap_restore);
ret = parasite_init(ctl, pid); ret = parasite_init(ctl, pid);
...@@ -626,7 +630,7 @@ err_fini: ...@@ -626,7 +630,7 @@ err_fini:
pr_panic("Can't finalize parasite (pid: %d) task\n", ctl->pid); pr_panic("Can't finalize parasite (pid: %d) task\n", ctl->pid);
err_munmap_restore: err_munmap_restore:
regs = regs_orig, regs.ip = vma_area->vma.start; regs = regs_orig, regs.ip = vma_area->vma.start;
if (munmap_seized(pid, &regs, mmaped, parasite_size)) if (munmap_seized(pid, &regs, ctl->remote_map, ctl->map_length))
pr_panic("mmap_seized failed (pid: %d)\n", pid); pr_panic("mmap_seized failed (pid: %d)\n", pid);
err_restore_regs: err_restore_regs:
if (ptrace(PTRACE_SETREGS, pid, NULL, &regs_orig)) if (ptrace(PTRACE_SETREGS, pid, NULL, &regs_orig))
......
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