[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 03:47:44 EDT 2012
Otherwise the restore procedure might refuse to continue.
Signed-off-by: Cyrill Gorcunov <gorcunov at openvz.org>
---
restorer.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++++----------
1 files changed, 54 insertions(+), 12 deletions(-)
diff --git a/restorer.c b/restorer.c
index 0160108..f4ea6f8 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 imples 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,7 @@ long restore_task(struct task_restore_core_args *args)
futex_set_and_wake(&entry->lock, 1);
}
- if (vma_entry->prot & PROT_WRITE)
- continue;
-
+ setup_mm_special(args, vma_entry);
sys_mprotect(vma_entry->start,
vma_entry_len(vma_entry),
vma_entry->prot);
@@ -428,11 +475,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