[CRIU] [PATCH] dump: unprotect vmas for dumping content
Andrey Vagin
avagin at openvz.org
Fri Mar 29 11:52:51 EDT 2013
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: Andrey Vagin <avagin at openvz.org>
---
cr-dump.c | 4 +---
include/parasite-syscall.h | 3 +++
include/parasite.h | 14 +++++++++++
parasite-syscall.c | 60 +++++++++++++++++++++++++++++++++++++++++++++-
pie/parasite.c | 20 ++++++++++++++++
5 files changed, 97 insertions(+), 4 deletions(-)
diff --git a/cr-dump.c b/cr-dump.c
index 8089331..c8e2779 100644
--- a/cr-dump.c
+++ b/cr-dump.c
@@ -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) {
diff --git a/include/parasite-syscall.h b/include/parasite-syscall.h
index 6965470..bc75984 100644
--- a/include/parasite-syscall.h
+++ b/include/parasite-syscall.h
@@ -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;
diff --git a/include/parasite.h b/include/parasite.h
index 62c4179..5e4143c 100644
--- a/include/parasite.h
+++ b/include/parasite.h
@@ -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;
diff --git a/parasite-syscall.c b/parasite-syscall.c
index c723bc8..d82995e 100644
--- a/parasite-syscall.c
+++ b/parasite-syscall.c
@@ -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;
}
diff --git a/pie/parasite.c b/pie/parasite.c
index bfda754..9acb138 100644
--- a/pie/parasite.c
+++ b/pie/parasite.c
@@ -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:
--
1.7.11.7
More information about the CRIU
mailing list