[CRIU] [PATCH cr 08/16] restore: don't unmap premmapped private vma-s

Andrey Vagin avagin at openvz.org
Tue Oct 23 06:02:20 EDT 2012


Private vma-s are mapped before forking children, then they are
remapped to corrected places in restorer.c.

In restorer all unneeded vma-s are unmaped. VMA-s from premmapped
regions should not be unmaped.

Signed-off-by: Andrey Vagin <avagin at openvz.org>
---
 cr-restore.c       |   41 +++++++++++++++++++++++++++++++++++++++--
 include/restorer.h |    2 ++
 restorer.c         |    4 ++++
 3 files changed, 45 insertions(+), 2 deletions(-)

diff --git a/cr-restore.c b/cr-restore.c
index b11fae3..1f22df0 100644
--- a/cr-restore.c
+++ b/cr-restore.c
@@ -66,6 +66,8 @@ static int prepare_restorer_blob(void);
 
 static LIST_HEAD(vma_list);
 static int nr_vmas;
+static void *premmapped_addr;
+static unsigned long premmapped_len;
 
 static int shmem_remap(void *old_addr, void *new_addr, unsigned long size)
 {
@@ -231,6 +233,23 @@ static int map_private_vma(pid_t pid, struct vma_area *vma, void *tgt_addr,
 	return 0;
 }
 
+/* Prevent merging vma-s outside and inside the premmapped region */
+static int unmap_priv_guard_pages()
+{
+	if (munmap(premmapped_addr, PAGE_SIZE)) {
+		pr_perror("Could not unmap a guard page %p", premmapped_addr);
+		return -1;
+	}
+
+	if (munmap(premmapped_addr + premmapped_len - PAGE_SIZE, PAGE_SIZE)) {
+		pr_perror("Could not unmap a guard page %p",
+				premmapped_addr + premmapped_len);
+		return -1;
+	}
+
+	return 0;
+}
+
 static int read_vmas(int pid)
 {
 	int fd, ret = 0;
@@ -280,13 +299,26 @@ static int read_vmas(int pid)
 		priv_size += vma_area_len(vma);
 	}
 
-	/* Reserve a place for mapping private vma-s one by one */
-	addr = mmap(NULL, priv_size, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
+	/*
+	 * Reserve a place for mapping private vma-s one by one.
+	 *
+	 * Add two guard pages from both sides. This pages will be
+	 * unmaped before reading a current vmas for this process.
+	 * In this case we can be sure, that vmas outside and inside
+	 * of the premmapped region are not merged to each other.
+	 */
+	addr = mmap(NULL, priv_size + 2 * PAGE_SIZE,
+			PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
 	if (addr == MAP_FAILED) {
 		pr_perror("Unable to reserve memory");
 		return -1;
 	}
 
+	premmapped_addr = addr;
+	premmapped_len = priv_size + 2 * PAGE_SIZE;
+
+	addr += PAGE_SIZE;
+
 	list_for_each_entry(vma, &vma_list, list) {
 		if (!vma_priv(&vma->vma))
 			continue;
@@ -1433,6 +1465,9 @@ static int sigreturn_restore(pid_t pid, CoreEntry *core, struct list_head *tgt_v
 	restore_task_vma_len	= 0;
 	restore_thread_vma_len	= 0;
 
+	if (unmap_priv_guard_pages())
+		goto err;
+
 	ret = parse_smaps(pid, &self_vma_list, false);
 	close_proc();
 	if (ret < 0)
@@ -1545,6 +1580,8 @@ static int sigreturn_restore(pid_t pid, CoreEntry *core, struct list_head *tgt_v
 
 	mem += self_vmas_len;
 	task_args->tgt_vmas = vma_list_remap(mem, vmas_len, tgt_vmas);
+	task_args->premmapped_addr = (unsigned long) premmapped_addr;
+	task_args->premmapped_len = premmapped_len;
 	if (!task_args->tgt_vmas)
 		goto err;
 
diff --git a/include/restorer.h b/include/restorer.h
index 93e4160..aed8ea2 100644
--- a/include/restorer.h
+++ b/include/restorer.h
@@ -89,6 +89,8 @@ struct task_restore_core_args {
 	struct task_entries		*task_entries;
 	VmaEntry			*self_vmas;
 	VmaEntry			*tgt_vmas;
+	unsigned long			premmapped_addr;
+	unsigned long			premmapped_len;
 	rt_sigaction_t			sigchld_act;
 
 	struct itimerval		itimers[3];
diff --git a/restorer.c b/restorer.c
index 04337a9..1a5cff0 100644
--- a/restorer.c
+++ b/restorer.c
@@ -321,6 +321,10 @@ long __export_restore_task(struct task_restore_core_args *args)
 		if (!vma_entry_is(vma_entry, VMA_AREA_REGULAR))
 			continue;
 
+		if (args->premmapped_addr <= vma_entry->start &&
+		    vma_entry->end <= args->premmapped_addr + args->premmapped_len)
+			continue;
+
 		if (sys_munmap((void *)vma_entry->start, vma_entry_len(vma_entry))) {
 			pr_err("Munmap fail for %lx\n", vma_entry->start);
 			goto core_restore_end;
-- 
1.7.1



More information about the CRIU mailing list