Commit b71f9e80 authored by Pavel Emelyanov's avatar Pavel Emelyanov

vma: Introduce list-of-vmas object

Right now when we collect list of vmas we need to know the
number of elements in it. In the future I will need to know
more, so it makes sense to create a vmas-list object for it.
Signed-off-by: 's avatarPavel Emelyanov <xemul@parallels.com>
parent 7a7506f6
......@@ -62,20 +62,21 @@
static char loc_buf[PAGE_SIZE];
static int pidns_proc = -1;
void free_mappings(struct list_head *vma_area_list)
void free_mappings(struct vm_area_list *vma_area_list)
{
struct vma_area *vma_area, *p;
list_for_each_entry_safe(vma_area, p, vma_area_list, list) {
list_for_each_entry_safe(vma_area, p, &vma_area_list->h, list) {
if (vma_area->vm_file_fd > 0)
close(vma_area->vm_file_fd);
free(vma_area);
}
INIT_LIST_HEAD(vma_area_list);
INIT_LIST_HEAD(&vma_area_list->h);
vma_area_list->nr = 0;
}
int collect_mappings(pid_t pid, struct list_head *vma_area_list)
int collect_mappings(pid_t pid, struct vm_area_list *vma_area_list)
{
int ret = -1;
......@@ -87,11 +88,9 @@ int collect_mappings(pid_t pid, struct list_head *vma_area_list)
if (ret < 0)
goto err;
pr_info_vma_list(vma_area_list);
pr_info_vma_list(&vma_area_list->h);
pr_info("----------------------------------------\n");
ret = 0;
err:
return ret;
}
......@@ -300,7 +299,7 @@ static int dump_filemap(pid_t pid, VmaEntry *vma, int file_fd,
return dump_one_reg_file(file_fd, vma->shmid, &p);
}
static int dump_task_mappings(pid_t pid, const struct list_head *vma_area_list,
static int dump_task_mappings(pid_t pid, const struct vm_area_list *vma_area_list,
const struct cr_fdset *cr_fdset)
{
struct vma_area *vma_area;
......@@ -312,7 +311,7 @@ static int dump_task_mappings(pid_t pid, const struct list_head *vma_area_list,
fd = fdset_fd(cr_fdset, CR_FD_VMAS);
list_for_each_entry(vma_area, vma_area_list, list) {
list_for_each_entry(vma_area, &vma_area_list->h, list) {
VmaEntry *vma = &vma_area->vma;
pr_info_vma(vma_area);
......@@ -610,7 +609,7 @@ static int dump_task_ids(struct pstree_item *item, const struct cr_fdset *cr_fds
static int dump_task_core_all(pid_t pid, const struct proc_pid_stat *stat,
const struct parasite_dump_misc *misc, const struct parasite_ctl *ctl,
const struct cr_fdset *cr_fdset,
struct list_head *vma_area_list)
struct vm_area_list *vma_area_list)
{
int fd_core = fdset_fd(cr_fdset, CR_FD_CORE);
CoreEntry *core;
......@@ -632,7 +631,7 @@ static int dump_task_core_all(pid_t pid, const struct proc_pid_stat *stat,
if (ret)
goto err_free;
mark_stack_vma(CORE_THREAD_ARCH_INFO(core)->gpregs->sp, vma_area_list);
mark_stack_vma(CORE_THREAD_ARCH_INFO(core)->gpregs->sp, &vma_area_list->h);
ret = get_task_futex_robust_list(pid, core->thread_core);
if (ret)
......@@ -1240,7 +1239,7 @@ err:
static int dump_one_task(struct pstree_item *item)
{
pid_t pid = item->pid.real;
LIST_HEAD(vma_area_list);
struct vm_area_list vmas;
struct parasite_ctl *parasite_ctl;
int ret = -1;
struct parasite_dump_misc misc;
......@@ -1268,7 +1267,7 @@ static int dump_one_task(struct pstree_item *item)
if (ret < 0)
goto err;
ret = collect_mappings(pid, &vma_area_list);
ret = collect_mappings(pid, &vmas);
if (ret) {
pr_err("Collect mappings (pid: %d) failed with %d\n", pid, ret);
goto err;
......@@ -1281,7 +1280,7 @@ static int dump_one_task(struct pstree_item *item)
}
ret = -1;
parasite_ctl = parasite_infect_seized(pid, item, &vma_area_list, dfds);
parasite_ctl = parasite_infect_seized(pid, item, &vmas, dfds);
if (!parasite_ctl) {
pr_err("Can't infect (pid: %d) with parasite\n", pid);
goto err;
......@@ -1336,7 +1335,7 @@ static int dump_one_task(struct pstree_item *item)
}
}
ret = parasite_dump_pages_seized(parasite_ctl, &vma_area_list, cr_fdset);
ret = parasite_dump_pages_seized(parasite_ctl, &vmas, cr_fdset);
if (ret) {
pr_err("Can't dump pages (pid: %d) with parasite\n", pid);
goto err_cure;
......@@ -1355,7 +1354,7 @@ static int dump_one_task(struct pstree_item *item)
}
ret = dump_task_core_all(pid, &pps_buf, &misc,
parasite_ctl, cr_fdset, &vma_area_list);
parasite_ctl, cr_fdset, &vmas);
if (ret) {
pr_err("Dump core (pid: %d) failed with %d\n", pid, ret);
goto err_cure;
......@@ -1379,7 +1378,7 @@ static int dump_one_task(struct pstree_item *item)
goto err;
}
ret = dump_task_mappings(pid, &vma_area_list, cr_fdset);
ret = dump_task_mappings(pid, &vmas, cr_fdset);
if (ret) {
pr_err("Dump mappings (pid: %d) failed with %d\n", pid, ret);
goto err;
......@@ -1401,7 +1400,7 @@ static int dump_one_task(struct pstree_item *item)
err:
close_pid_proc();
err_free:
free_mappings(&vma_area_list);
free_mappings(&vmas);
xfree(dfds);
return ret;
......
......@@ -84,7 +84,7 @@ int cr_exec(int pid, char **opt)
char *sys_name = opt[0];
struct syscall_exec_desc *si;
struct parasite_ctl *ctl;
LIST_HEAD(vma_area_list);
struct vm_area_list vmas;
int ret = -1, prev_state;
if (!sys_name) {
......@@ -104,13 +104,13 @@ int cr_exec(int pid, char **opt)
goto out;
}
ret = collect_mappings(pid, &vma_area_list);
ret = collect_mappings(pid, &vmas);
if (ret) {
pr_err("Can't collect vmas for %d\n", pid);
goto out_unseize;
}
ctl = parasite_prep_ctl(pid, &vma_area_list);
ctl = parasite_prep_ctl(pid, &vmas);
if (!ctl) {
pr_err("Can't prep ctl %d\n", pid);
goto out_unseize;
......
......@@ -70,8 +70,7 @@ static int restore_task_with_children(void *);
static int sigreturn_restore(pid_t pid, CoreEntry *core);
static int prepare_restorer_blob(void);
static LIST_HEAD(rst_vma_list);
static int rst_nr_vmas;
static VM_AREA_LIST(rst_vmas);
static int shmem_remap(void *old_addr, void *new_addr, unsigned long size)
{
......@@ -267,7 +266,7 @@ static int restore_priv_vma_content(pid_t pid)
unsigned int nr_shared = 0;
unsigned int nr_droped = 0;
vma = list_first_entry(&rst_vma_list, struct vma_area, list);
vma = list_first_entry(&rst_vmas.h, struct vma_area, list);
fd = open_image_ro(CR_FD_PAGES, pid);
if (fd < 0)
......@@ -293,7 +292,7 @@ static int restore_priv_vma_content(pid_t pid)
BUG_ON(va < vma->vma.start);
while (va >= vma->vma.end) {
BUG_ON(vma->list.next == &rst_vma_list);
BUG_ON(vma->list.next == &rst_vmas.h);
vma = list_entry(vma->list.next, struct vma_area, list);
}
......@@ -322,7 +321,7 @@ static int restore_priv_vma_content(pid_t pid)
close(fd);
/* Remove pages, which were not shared with a child */
list_for_each_entry(vma, &rst_vma_list, list) {
list_for_each_entry(vma, &rst_vmas.h, list) {
unsigned long size, i = 0;
void *addr = decode_pointer(vma_premmaped_start(&vma->vma));
......@@ -366,8 +365,8 @@ static int read_vmas(int pid)
void *old_premmapped_addr = NULL;
unsigned long old_premmapped_len, pstart = 0;
rst_nr_vmas = 0;
list_replace_init(&rst_vma_list, &old);
rst_vmas.nr = 0;
list_replace_init(&rst_vmas.h, &old);
/* Skip errors, because a zombie doesn't have an image of vmas */
fd = open_image_ro(CR_FD_VMAS, pid);
......@@ -390,8 +389,8 @@ static int read_vmas(int pid)
if (ret <= 0)
break;
rst_nr_vmas++;
list_add_tail(&vma->list, &rst_vma_list);
rst_vmas.nr++;
list_add_tail(&vma->list, &rst_vmas.h);
if (e->fd != -1) {
ret = -1;
......@@ -423,7 +422,7 @@ static int read_vmas(int pid)
pvma = list_entry(&old, struct vma_area, list);
list_for_each_entry(vma, &rst_vma_list, list) {
list_for_each_entry(vma, &rst_vmas.h, list) {
if (pstart > vma->vma.start) {
ret = -1;
pr_err("VMA-s are not sorted in the image file\n");
......@@ -468,7 +467,7 @@ static int open_vmas(int pid)
struct vma_area *vma;
int ret = 0;
list_for_each_entry(vma, &rst_vma_list, list) {
list_for_each_entry(vma, &rst_vmas.h, list) {
if (!(vma_entry_is(&vma->vma, VMA_AREA_REGULAR)))
continue;
......@@ -1445,7 +1444,7 @@ static int prepare_creds(int pid, struct task_restore_core_args *args)
return 0;
}
static VmaEntry *vma_list_remap(void *addr, unsigned long len, struct list_head *vmas)
static VmaEntry *vma_list_remap(void *addr, unsigned long len, struct vm_area_list *vmas)
{
VmaEntry *vma, *ret;
struct vma_area *vma_area;
......@@ -1457,7 +1456,7 @@ static VmaEntry *vma_list_remap(void *addr, unsigned long len, struct list_head
return NULL;
}
list_for_each_entry(vma_area, vmas, list) {
list_for_each_entry(vma_area, &vmas->h, list) {
*vma = vma_area->vma;
vma++;
}
......@@ -1656,7 +1655,7 @@ static int sigreturn_restore(pid_t pid, CoreEntry *core)
struct task_restore_core_args *task_args;
struct thread_restore_args *thread_args;
LIST_HEAD(self_vma_list);
struct vm_area_list self_vmas;
int i;
pr_info("Restore via sigreturn\n");
......@@ -1664,16 +1663,16 @@ static int sigreturn_restore(pid_t pid, CoreEntry *core)
restore_task_vma_len = 0;
restore_thread_vma_len = 0;
ret = parse_smaps(pid, &self_vma_list, false);
ret = parse_smaps(pid, &self_vmas, false);
close_proc();
if (ret < 0)
goto err;
/* required to unmap stack _with_ guard page */
mark_stack_vma((long) &self_vma_list, &self_vma_list);
mark_stack_vma((long) &self_vmas, &self_vmas.h);
self_vmas_len = round_up((ret + 1) * sizeof(VmaEntry), PAGE_SIZE);
vmas_len = round_up((rst_nr_vmas + 1) * sizeof(VmaEntry), PAGE_SIZE);
self_vmas_len = round_up((self_vmas.nr + 1) * sizeof(VmaEntry), PAGE_SIZE);
vmas_len = round_up((rst_vmas.nr + 1) * sizeof(VmaEntry), PAGE_SIZE);
/* pr_info_vma_list(&self_vma_list); */
......@@ -1707,7 +1706,7 @@ static int sigreturn_restore(pid_t pid, CoreEntry *core)
* or inited from scratch).
*/
exec_mem_hint = restorer_get_vma_hint(pid, &rst_vma_list, &self_vma_list,
exec_mem_hint = restorer_get_vma_hint(pid, &rst_vmas.h, &self_vmas.h,
restore_bootstrap_len);
if (exec_mem_hint == -1) {
pr_err("No suitable area for task_restore bootstrap (%ldK)\n",
......@@ -1769,13 +1768,13 @@ static int sigreturn_restore(pid_t pid, CoreEntry *core)
task_args->task_entries = mem;
mem += TASK_ENTRIES_SIZE;
task_args->self_vmas = vma_list_remap(mem, self_vmas_len, &self_vma_list);
task_args->self_vmas = vma_list_remap(mem, self_vmas_len, &self_vmas);
if (!task_args->self_vmas)
goto err;
mem += self_vmas_len;
task_args->tgt_vmas = vma_list_remap(mem, vmas_len, &rst_vma_list);
task_args->nr_vmas = rst_nr_vmas;
task_args->nr_vmas = rst_vmas.nr;
task_args->tgt_vmas = vma_list_remap(mem, vmas_len, &rst_vmas);
task_args->premmapped_addr = (unsigned long) current->rst->premmapped_addr;
task_args->premmapped_len = current->rst->premmapped_len;
if (!task_args->tgt_vmas)
......@@ -1924,7 +1923,7 @@ static int sigreturn_restore(pid_t pid, CoreEntry *core)
JUMP_TO_RESTORER_BLOB(new_sp, restore_task_exec_start, task_args);
err:
free_mappings(&self_vma_list);
free_mappings(&self_vmas);
/* Just to be sure */
exit(1);
......
......@@ -216,8 +216,15 @@ struct cr_fdset *cr_glob_fdset_open(int mode);
void close_cr_fdset(struct cr_fdset **cr_fdset);
int collect_mappings(pid_t pid, struct list_head *vma_area_list);
void free_mappings(struct list_head *vma_area_list);
struct vm_area_list {
struct list_head h;
unsigned nr;
};
#define VM_AREA_LIST(name) struct vm_area_list name = { .h = LIST_HEAD_INIT(name.h), .nr = 0, }
int collect_mappings(pid_t pid, struct vm_area_list *vma_area_list);
void free_mappings(struct vm_area_list *vma_area_list);
struct vma_area {
struct list_head list;
......
......@@ -30,11 +30,12 @@ extern int parasite_dump_sigacts_seized(struct parasite_ctl *ctl, struct cr_fdse
extern int parasite_dump_itimers_seized(struct parasite_ctl *ctl, struct cr_fdset *cr_fdset);
struct parasite_dump_misc;
struct vm_area_list;
extern int parasite_dump_misc_seized(struct parasite_ctl *ctl, struct parasite_dump_misc *misc);
struct _CredsEntry;
extern int parasite_dump_creds(struct parasite_ctl *ctl, struct _CredsEntry *ce);
extern int parasite_dump_pages_seized(struct parasite_ctl *ctl,
struct list_head *vma_area_list,
struct vm_area_list *vma_area_list,
struct cr_fdset *cr_fdset);
struct parasite_dump_thread;
struct pid;
......@@ -53,9 +54,9 @@ struct pstree_item;
extern int parasite_cure_seized(struct parasite_ctl *ctl, struct pstree_item *item);
extern struct parasite_ctl *parasite_infect_seized(pid_t pid,
struct pstree_item *item,
struct list_head *vma_area_list,
struct vm_area_list *vma_area_list,
struct parasite_drain_fd *dfds);
extern struct parasite_ctl *parasite_prep_ctl(pid_t pid, struct list_head *vma_area_list);
extern struct parasite_ctl *parasite_prep_ctl(pid_t pid, struct vm_area_list *vma_area_list);
extern int parasite_map_exchange(struct parasite_ctl *ctl, unsigned long size);
extern struct parasite_tty_args *parasite_dump_tty(struct parasite_ctl *ctl, int fd);
......
......@@ -123,10 +123,12 @@ static inline void mnt_entry_init(struct mount_info *pm)
INIT_LIST_HEAD(&pm->children);
}
struct vm_area_list;
extern struct mount_info *parse_mountinfo(pid_t pid);
extern int parse_pid_stat(pid_t pid, struct proc_pid_stat *s);
extern int parse_pid_stat_small(pid_t pid, struct proc_pid_stat_small *s);
extern int parse_smaps(pid_t pid, struct list_head *vma_area_list, bool use_map_files);
extern int parse_smaps(pid_t pid, struct vm_area_list *vma_area_list, bool use_map_files);
extern int parse_pid_status(pid_t pid, struct proc_status_creds *);
union fdinfo_entries {
......
......@@ -486,7 +486,7 @@ int parasite_dump_creds(struct parasite_ctl *ctl, CredsEntry *ce)
* This routine drives parasite code (been previously injected into a victim
* process) and tells it to dump pages into the file.
*/
int parasite_dump_pages_seized(struct parasite_ctl *ctl, struct list_head *vma_area_list,
int parasite_dump_pages_seized(struct parasite_ctl *ctl, struct vm_area_list *vma_area_list,
struct cr_fdset *cr_fdset)
{
struct parasite_dump_pages_args *parasite_dumppages;
......@@ -510,7 +510,7 @@ int parasite_dump_pages_seized(struct parasite_ctl *ctl, struct list_head *vma_a
parasite_dumppages = parasite_args(ctl, struct parasite_dump_pages_args);
list_for_each_entry(vma_area, vma_area_list, list) {
list_for_each_entry(vma_area, &vma_area_list->h, list) {
/*
* The special areas are not dumped.
......@@ -708,7 +708,7 @@ int parasite_cure_seized(struct parasite_ctl *ctl, struct pstree_item *item)
return ret;
}
struct parasite_ctl *parasite_prep_ctl(pid_t pid, struct list_head *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 vma_area *vma_area;
......@@ -734,7 +734,7 @@ struct parasite_ctl *parasite_prep_ctl(pid_t pid, struct list_head *vma_area_lis
goto err;
}
vma_area = get_vma_by_ip(vma_area_list, REG_IP(ctl->regs_orig));
vma_area = get_vma_by_ip(&vma_area_list->h, REG_IP(ctl->regs_orig));
if (!vma_area) {
pr_err("No suitable VMA found to run parasite "
"bootstrap code (pid: %d)\n", pid);
......@@ -804,7 +804,7 @@ static unsigned long parasite_args_size(struct parasite_drain_fd *dfds)
}
struct parasite_ctl *parasite_infect_seized(pid_t pid, struct pstree_item *item,
struct list_head *vma_area_list, struct parasite_drain_fd *dfds)
struct vm_area_list *vma_area_list, struct parasite_drain_fd *dfds)
{
int ret;
struct parasite_ctl *ctl;
......
......@@ -166,18 +166,21 @@ static int is_anon_shmem_map(dev_t dev)
return shmem_dev == dev;
}
int parse_smaps(pid_t pid, struct list_head *vma_area_list, bool use_map_files)
int parse_smaps(pid_t pid, struct vm_area_list *vma_area_list, bool use_map_files)
{
struct vma_area *vma_area = NULL;
unsigned long start, end, pgoff;
unsigned long ino;
char r, w, x, s;
int dev_maj, dev_min;
int ret = -1, nr = 0;
int ret = -1;
DIR *map_files_dir = NULL;
FILE *smaps = NULL;
vma_area_list->nr = 0;
INIT_LIST_HEAD(&vma_area_list->h);
smaps = fopen_proc(pid, "smaps");
if (!smaps)
goto err;
......@@ -340,12 +343,12 @@ int parse_smaps(pid_t pid, struct list_head *vma_area_list, bool use_map_files)
vma_area->vma.flags |= MAP_ANONYMOUS;
}
done:
list_add_tail(&vma_area->list, vma_area_list);
nr++;
list_add_tail(&vma_area->list, &vma_area_list->h);
vma_area_list->nr++;
}
vma_area = NULL;
ret = nr;
ret = 0;
err:
if (smaps)
......
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