: [CRIU] [PATCH] restorer: Make sure the protection on code/data mm areas do fit the kernel requirements

Cyrill Gorcunov gorcunov at openvz.org
Fri Apr 13 06:34:38 EDT 2012


On Fri, Apr 13, 2012 at 01:24:40PM +0400, Pavel Emelyanov wrote:
> 
> You don't use the flags value after this AT ALL, wtf???
> 

This one should do the trick.

	Cyrill
-------------- next part --------------
>From 0cb523f707723a67d121b2b5fcf7905671742477 Mon Sep 17 00:00:00 2001
From: Cyrill Gorcunov <gorcunov at openvz.org>
Date: Fri, 13 Apr 2012 14:28:32 +0400
Subject: [PATCH] restorer: Setup mm::code/data addresses via setup_mm_special

When set up mm::code/data addresses the kernel expects
the correspond VMAs to have predefined protection, but
task might have dropped or mprotected those VMAs at moment
of checkpoint. So just setup fake VMAs, call prctl and
munmap them immediately.

Signed-off-by: Cyrill Gorcunov <gorcunov at openvz.org>
---
 restorer.c |   59 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
 1 files changed, 54 insertions(+), 5 deletions(-)

diff --git a/restorer.c b/restorer.c
index 0160108..680b814 100644
--- a/restorer.c
+++ b/restorer.c
@@ -244,6 +244,50 @@ static long restore_self_exe_late(struct task_restore_core_args *args)
 	return 0;
 }
 
+/*
+ * The kernel applies special requirements for code/data protection
+ * when setting up mm::code/data start and end addresses, so just
+ * setup fake areas which suits it and unmap them once prctl finished.
+ */
+static int setup_mm_special(struct task_restore_core_args *args)
+{
+	const int flags = MAP_PRIVATE | MAP_FIXED;
+	int ret = 0;
+	int prot;
+
+	prot = PROT_EXEC | PROT_READ;
+	sys_mmap((void *)args->mm.mm_start_code, PAGE_SIZE, prot, flags, -1, 0);
+	ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_START_CODE, (long)args->mm.mm_start_code, 0);
+	sys_munmap((void *)args->mm.mm_start_code, PAGE_SIZE);
+
+	sys_mmap((void *)args->mm.mm_end_code, PAGE_SIZE, PROT_EXEC | PROT_READ, flags, -1, 0);
+	ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_END_CODE, (long)args->mm.mm_end_code, 0);
+	sys_munmap((void *)args->mm.mm_end_code, PAGE_SIZE);
+
+	if (ret) {
+		write_num_n(__LINE__);
+		write_num_n(ret);
+		return -1;
+	}
+
+	prot = PROT_READ | PROT_WRITE;
+	sys_mmap((void *)args->mm.mm_start_data, PAGE_SIZE, PROT_READ | PROT_WRITE, flags, -1, 0);
+	ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_START_DATA, (long)args->mm.mm_start_data, 0);
+	sys_munmap((void *)args->mm.mm_start_data, PAGE_SIZE);
+
+	sys_mmap((void *)args->mm.mm_end_data, PAGE_SIZE, PROT_READ | PROT_WRITE, flags, -1, 0);
+	ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_END_DATA, (long)args->mm.mm_end_data, 0);
+	sys_munmap((void *)args->mm.mm_end_data, PAGE_SIZE);
+
+	if (ret) {
+		write_num_n(__LINE__);
+		write_num_n(ret);
+		return -1;
+	}
+
+	return 0;
+}
+
 static u64 restore_mapping(const struct vma_entry *vma_entry)
 {
 	int prot	= vma_entry->prot;
@@ -340,6 +384,16 @@ long restore_task(struct task_restore_core_args *args)
 			((void *)(vma_entry + 1) - ((void *)args->self_vmas)));
 
 	/*
+	 * Some fields of mm descriptor need to
+	 * be prepared on bare memory map.
+	 */
+	if (setup_mm_special(args)) {
+		write_num_n(__LINE__);
+		write_num_n(ret);
+		goto core_restore_end;
+	}
+
+	/*
 	 * OK, lets try to map new one.
 	 */
 	for (vma_entry = args->tgt_vmas; vma_entry->start != 0; vma_entry++) {
@@ -428,11 +482,6 @@ long restore_task(struct task_restore_core_args *args)
 	 * Tune up the task fields.
 	 */
 	ret |= sys_prctl_safe(PR_SET_NAME, (long)core_entry->tc.comm, 0, 0);
-
-	ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_START_CODE,	(long)args->mm.mm_start_code, 0);
-	ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_END_CODE,	(long)args->mm.mm_end_code, 0);
-	ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_START_DATA,	(long)args->mm.mm_start_data, 0);
-	ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_END_DATA,	(long)args->mm.mm_end_data, 0);
 	ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_START_STACK,	(long)args->mm.mm_start_stack, 0);
 	ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_START_BRK,	(long)args->mm.mm_start_brk, 0);
 	ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_BRK,		(long)args->mm.mm_brk, 0);
-- 
1.7.7.6



More information about the CRIU mailing list