: [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 04:52:59 EDT 2012


On Fri, Apr 13, 2012 at 12:49:28PM +0400, Cyrill Gorcunov wrote:
> > > + * Note, this imples the caller code will restore the original
> > 
> > implies
> > 
> 
> Thanks Kir. I'll update and send it out.
> 

Pavel, pick this one instead.

	Cyrill
-------------- next part --------------
>From 4d5b19d7fbef4208c3efef140609abb4faf560ff Mon Sep 17 00:00:00 2001
From: Cyrill Gorcunov <gorcunov at openvz.org>
Date: Fri, 13 Apr 2012 12:51:48 +0400
Subject: [PATCH] restorer: Make sure the protection on code/data mm areas do
 fit the kernel requirements

Otherwise the restore procedure might refuse to continue.

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

diff --git a/restorer.c b/restorer.c
index 0160108..b90c0fc 100644
--- a/restorer.c
+++ b/restorer.c
@@ -244,7 +244,56 @@ static long restore_self_exe_late(struct task_restore_core_args *args)
 	return 0;
 }
 
-static u64 restore_mapping(const struct vma_entry *vma_entry)
+/*
+ * The kernel applies special requirements for code/data protection,
+ * thus we setup the flags needed here.
+ *
+ * Note, this implies the caller code will restore the original
+ * protection later. Also for code section the write flag is cleared,
+ * so make sure you already uploaded page contents if needed.
+ */
+static int setup_mm_special(struct task_restore_core_args *args,
+			    const struct vma_entry *vma_entry)
+{
+	int flags = vma_entry->flags;
+	int ret = 0;
+
+	if (vma_entry->start == (long)args->mm.mm_start_code ||
+	    vma_entry->end == (long)args->mm.mm_end_code) {
+		flags |= PROT_EXEC | PROT_READ;
+		flags &= ~PROT_WRITE;
+
+		sys_mprotect(vma_entry->start,
+			     vma_entry_len(vma_entry),
+			     flags);
+
+		if (vma_entry->start == (long)args->mm.mm_start_code)
+			ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_START_CODE,
+					      (long)args->mm.mm_start_code, 0);
+		else
+			ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_END_CODE,
+					      (long)args->mm.mm_end_code, 0);
+
+	}
+
+	if (vma_entry->start == (long)args->mm.mm_start_data ||
+		vma_entry->end == (long)args->mm.mm_end_data) {
+		flags |= PROT_READ | PROT_WRITE;
+		flags &= ~PROT_EXEC;
+
+		if (vma_entry->start == (long)args->mm.mm_start_data)
+			ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_START_DATA,
+					      (long)args->mm.mm_start_data, 0);
+		else
+			ret |= sys_prctl_safe(PR_SET_MM, PR_SET_MM_END_DATA,
+					      (long)args->mm.mm_end_data, 0);
+	}
+
+	return ret;
+}
+
+static u64 restore_mapping(struct task_restore_core_args *args,
+			   const struct vma_entry *vma_entry)
 {
 	int prot	= vma_entry->prot;
 	int flags	= vma_entry->flags | MAP_FIXED;
@@ -346,7 +395,7 @@ long restore_task(struct task_restore_core_args *args)
 		if (!vma_entry_is(vma_entry, VMA_AREA_REGULAR))
 			continue;
 
-		va = restore_mapping(vma_entry);
+		va = restore_mapping(args, vma_entry);
 
 		if (va != vma_entry->start) {
 			write_num_n(__LINE__);
@@ -386,8 +435,8 @@ long restore_task(struct task_restore_core_args *args)
 	sys_close(args->fd_pages);
 
 	/*
-	 * Walk though all VMAs again to drop PROT_WRITE
-	 * if it was not there.
+	 * Walk though all VMAs again to restore
+	 * original protection.
 	 */
 	for (vma_entry = args->tgt_vmas; vma_entry->start != 0; vma_entry++) {
 		if (!(vma_entry_is(vma_entry, VMA_AREA_REGULAR)))
@@ -403,9 +452,11 @@ long restore_task(struct task_restore_core_args *args)
 				futex_set_and_wake(&entry->lock, 1);
 		}
 
-		if (vma_entry->prot & PROT_WRITE)
-			continue;
-
+		if (setup_mm_special(args, vma_entry)) {
+			write_num_n(__LINE__);
+			write_num_n(ret);
+			goto core_restore_end;
+		}
 		sys_mprotect(vma_entry->start,
 			     vma_entry_len(vma_entry),
 			     vma_entry->prot);
@@ -428,11 +479,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