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)
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) {
pr_err("Can't infect (pid: %d) with parasite\n", pid);
goto err;
......
......@@ -14,7 +14,9 @@
/* parasite control block */
struct parasite_ctl {
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 addr_cmd; /* addr for command */
unsigned long addr_args; /* address for arguments */
......@@ -30,7 +32,7 @@ extern int parasite_dump_itimers_seized(struct parasite_ctl *ctl, struct cr_fdse
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);
#endif /* PARASITE_SYSCALL_H_ */
......@@ -527,9 +527,7 @@ int parasite_cure_seized(struct parasite_ctl *ctl, struct list_head *vma_area_li
regs.ip = vma_area->vma.start;
ret = munmap_seized(ctl->pid, &regs,
(void *)ctl->vma_area.vma.start,
(size_t)vma_entry_len(&ctl->vma_area.vma));
ret = munmap_seized(ctl->pid, &regs, ctl->remote_map, ctl->map_length);
if (ret)
pr_err("munmap_seized failed (pid: %d)\n", ctl->pid);
......@@ -543,14 +541,14 @@ err:
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 = { };
user_regs_struct_t regs, regs_orig;
struct parasite_ctl *ctl = NULL;
struct vma_area *vma_area;
void *mmaped;
int ret;
char fname[128];
int ret, fd;
ctl = xzalloc(sizeof(*ctl));
if (!ctl) {
......@@ -572,37 +570,43 @@ struct parasite_ctl *parasite_infect_seized(pid_t pid, struct list_head *vma_are
}
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;
mmaped = mmap_seized(pid, &regs, NULL, (size_t)parasite_size,
(int)ctl->vma_area.vma.prot,
(int)ctl->vma_area.vma.flags,
(int)-1, (off_t)0);
ctl->remote_map = mmap_seized(pid, &regs, NULL, (size_t)parasite_size,
PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_ANONYMOUS | MAP_SHARED, -1, 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);
goto err_restore_regs;
}
ctl->parasite_ip = PARASITE_HEAD_ADDR((unsigned long)mmaped);
ctl->addr_cmd = PARASITE_CMD_ADDR((unsigned long)mmaped);
ctl->addr_args = PARASITE_ARGS_ADDR((unsigned long)mmaped);
ctl->map_length = round_up(parasite_size, PAGE_SIZE);
ctl->vma_area.vma.start = (u64)mmaped;
ctl->vma_area.vma.end = (u64)(mmaped + parasite_size);
ctl->parasite_ip = PARASITE_HEAD_ADDR((unsigned long)ctl->remote_map);
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)) {
pr_err("Can't inject parasite blob (pid: %d)\n", pid);
snprintf(fname, sizeof(fname), "map_files/%p-%p",
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;
}
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);
ret = parasite_init(ctl, pid);
......@@ -626,7 +630,7 @@ err_fini:
pr_panic("Can't finalize parasite (pid: %d) task\n", ctl->pid);
err_munmap_restore:
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);
err_restore_regs:
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