Commit 6ed19e31 authored by Andrey Vagin's avatar Andrey Vagin Committed by Pavel Emelyanov

dump: unprotect vmas for dumping content

VMA-s may be protected against read, so rights for such VMA-s should be
changed for dumping and protected back after dumping.
Signed-off-by: 's avatarAndrey Vagin <avagin@openvz.org>
Signed-off-by: 's avatarPavel Emelyanov <xemul@parallels.com>
parent a6b13b38
......@@ -1431,10 +1431,8 @@ static int dump_one_task(struct pstree_item *item)
}
ret = parasite_dump_pages_seized(parasite_ctl, item->pid.virt, &vmas, cr_fdset);
if (ret) {
pr_err("Can't dump pages (pid: %d) with parasite\n", pid);
if (ret)
goto err_cure;
}
ret = parasite_dump_sigacts_seized(parasite_ctl, cr_fdset);
if (ret) {
......
......@@ -37,6 +37,9 @@ extern int parasite_dump_creds(struct parasite_ctl *ctl, struct _CredsEntry *ce)
extern int parasite_dump_pages_seized(struct parasite_ctl *ctl, int vpid,
struct vm_area_list *vma_area_list,
struct cr_fdset *cr_fdset);
extern int parasite_mprotect_seized(struct parasite_ctl *ctl,
struct vm_area_list *vma_area_list,
bool unprotect);
struct parasite_dump_thread;
struct pid;
struct _CoreEntry;
......
......@@ -24,6 +24,7 @@ enum {
PARASITE_CMD_FINI,
PARASITE_CMD_FINI_THREAD,
PARASITE_CMD_MPROTECT_VMAS,
PARASITE_CMD_DUMPPAGES,
PARASITE_CMD_DUMP_SIGACTS,
......@@ -52,6 +53,19 @@ struct parasite_log_args {
int log_level;
};
struct parasite_vma_entry
{
unsigned long start;
unsigned long len;
int prot;
};
struct parasite_mprotect_args
{
unsigned int nr;
struct parasite_vma_entry vmas[0];
};
struct parasite_dump_pages_args {
unsigned int off;
unsigned int nr;
......
......@@ -485,6 +485,12 @@ int parasite_dump_creds(struct parasite_ctl *ctl, CredsEntry *ce)
return 0;
}
static unsigned int vmas_mprotect_size(struct vm_area_list *vmas)
{
return sizeof(struct parasite_mprotect_args) +
(vmas->nr * sizeof(struct parasite_vma_entry));
}
static unsigned int vmas_pagemap_size(struct vm_area_list *vmas)
{
/*
......@@ -545,7 +551,35 @@ static int generate_iovs(struct vma_area *vma, int pagemap, struct page_pipe *pp
return 0;
}
int parasite_dump_pages_seized(struct parasite_ctl *ctl, int vpid,
int parasite_mprotect_seized(struct parasite_ctl *ctl, struct vm_area_list *vma_area_list, bool unprotect)
{
struct parasite_mprotect_args *args;
struct parasite_vma_entry *p_vma;
struct vma_area *vma;
args = parasite_args_s(ctl, vmas_pagemap_size(vma_area_list));
p_vma = args->vmas;
args->nr = 0;
list_for_each_entry(vma, &vma_area_list->h, list) {
if (!privately_dump_vma(vma))
continue;
if (vma->vma.prot & PROT_READ)
continue;
p_vma->start = vma->vma.start;
p_vma->len = vma_area_len(vma);
p_vma->prot = vma->vma.prot;
if (unprotect)
p_vma->prot |= PROT_READ;
args->nr++;
p_vma++;
}
return parasite_execute(PARASITE_CMD_MPROTECT_VMAS, ctl);
}
static int __parasite_dump_pages_seized(struct parasite_ctl *ctl, int vpid,
struct vm_area_list *vma_area_list, struct cr_fdset *cr_fdset)
{
struct parasite_dump_pages_args *args;
......@@ -624,6 +658,29 @@ out:
return ret;
}
int parasite_dump_pages_seized(struct parasite_ctl *ctl, int vpid,
struct vm_area_list *vma_area_list, struct cr_fdset *cr_fdset)
{
int ret;
ret = parasite_mprotect_seized(ctl, vma_area_list, true);
if (ret) {
pr_err("Can't dump unprotect vmas with parasite\n");
return ret;
}
ret = __parasite_dump_pages_seized(ctl, vpid, vma_area_list, cr_fdset);
if (ret)
pr_err("Can't dump page with parasite\n");
if (parasite_mprotect_seized(ctl, vma_area_list, false)) {
pr_err("Can't rollback unprotected vmas with parasite\n");
ret = -1;
}
return ret;
}
int parasite_drain_fds_seized(struct parasite_ctl *ctl,
struct parasite_drain_fd *dfds, int *lfds, struct fd_opts *opts)
{
......@@ -852,6 +909,7 @@ static unsigned long parasite_args_size(struct vm_area_list *vmas, struct parasi
size = max(size, (unsigned long)drain_fds_size(dfds));
size = max(size, (unsigned long)vmas_pagemap_size(vmas));
size = max(size, (unsigned long)vmas_mprotect_size(vmas));
return size;
}
......
......@@ -34,6 +34,24 @@ static unsigned int next_tid_state;
#define SPLICE_F_GIFT 0x08
#endif
static int mprotect_vmas(struct parasite_mprotect_args *args)
{
struct parasite_vma_entry *vma;
int ret = 0, i;
for (i = 0; i < args->nr; i++) {
vma = args->vmas + i;
ret = sys_mprotect((void *)vma->start, vma->len, vma->prot);
if (ret) {
pr_err("mprotect(%08lx, %lu) failed with code %d\n",
vma->start, vma->len, ret);
break;
}
}
return ret;
}
static int dump_pages(struct parasite_dump_pages_args *args)
{
int p, ret;
......@@ -425,6 +443,8 @@ int __used parasite_service(unsigned int cmd, void *args)
return parasite_cfg_log(args);
case PARASITE_CMD_DUMPPAGES:
return dump_pages(args);
case PARASITE_CMD_MPROTECT_VMAS:
return mprotect_vmas(args);
case PARASITE_CMD_DUMP_SIGACTS:
return dump_sigact(args);
case PARASITE_CMD_DUMP_ITIMERS:
......
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