[PATCHv3,19/30] restore: add arch_prctl mapping compatible vDSO

Submitted by Dmitry Safonov on June 28, 2016, 7:24 p.m.

Details

Message ID 20160628192423.14943-20-dsafonov@virtuozzo.com
State Rejected
Series "x86 Compatible C/R, part 2"
Headers show

Commit Message

Dmitry Safonov June 28, 2016, 7:24 p.m.
Map here instead of park before unmap.
TODO: need to check that mapped size is smaller than x86_64 vDSO.

Cc: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
---
 criu/cr-restore.c            |  1 +
 criu/include/parasite-vdso.h |  2 ++
 criu/include/restorer.h      |  2 ++
 criu/pie/parasite-vdso.c     | 20 ++++++++++++++++++++
 criu/pie/restorer.c          | 14 ++++++++++++--
 5 files changed, 37 insertions(+), 2 deletions(-)

Patch hide | download patch | download mbox

diff --git a/criu/cr-restore.c b/criu/cr-restore.c
index 84ed12634827..950f67b2698a 100644
--- a/criu/cr-restore.c
+++ b/criu/cr-restore.c
@@ -2901,6 +2901,7 @@  static int sigreturn_restore(pid_t pid, struct task_restore_args *task_args, uns
 	if (core->tc->has_seccomp_mode)
 		task_args->seccomp_mode = core->tc->seccomp_mode;
 
+	task_args->compatible_mode = core_is_compat(core);
 	/*
 	 * Arguments for task restoration.
 	 */
diff --git a/criu/include/parasite-vdso.h b/criu/include/parasite-vdso.h
index 530cc01cb5e4..d50319048264 100644
--- a/criu/include/parasite-vdso.h
+++ b/criu/include/parasite-vdso.h
@@ -80,12 +80,14 @@  static inline bool is_vdso_mark(void *addr)
 }
 
 extern int vdso_do_park(struct vdso_symtable *sym_rt, unsigned long park_at, unsigned long park_size);
+int vdso_map_compat(unsigned long map_at);
 extern int vdso_proxify(char *who, struct vdso_symtable *sym_rt,
 			unsigned long vdso_rt_parked_at, size_t index,
 			VmaEntry *vmas, size_t nr_vmas);
 
 #else /* CONFIG_VDSO */
 #define vdso_do_park(sym_rt, park_at, park_size)		(0)
+#define vdso_map_compat(map_at)					(0)
 
 #endif /* CONFIG_VDSO */
 
diff --git a/criu/include/restorer.h b/criu/include/restorer.h
index fad9e09b82ad..7c0336e7bf74 100644
--- a/criu/include/restorer.h
+++ b/criu/include/restorer.h
@@ -175,6 +175,8 @@  struct task_restore_args {
 
 	int				seccomp_mode;
 
+	bool				compatible_mode;
+
 #ifdef CONFIG_VDSO
 	unsigned long			vdso_rt_size;
 	struct vdso_symtable		vdso_sym_rt;		/* runtime vdso symbols */
diff --git a/criu/pie/parasite-vdso.c b/criu/pie/parasite-vdso.c
index 7f4e6a022594..b5d12f1e1ca7 100644
--- a/criu/pie/parasite-vdso.c
+++ b/criu/pie/parasite-vdso.c
@@ -68,6 +68,26 @@  int vdso_do_park(struct vdso_symtable *sym_rt, unsigned long park_at, unsigned l
 	return ret;
 }
 
+#ifdef CONFIG_X86_64
+#ifndef ARCH_MAP_VDSO_32
+# define ARCH_MAP_VDSO_32	0x2002
+#endif
+int vdso_map_compat(unsigned long map_at)
+{
+	int ret;
+
+	pr_debug("Mapping compatible vDSO at %lx\n", map_at);
+
+	ret = sys_arch_prctl(ARCH_MAP_VDSO_32, map_at);
+	return ret;
+}
+#else
+int vdso_map_compat(unsigned long map_at)
+{
+	return 0;
+}
+#endif
+
 int vdso_proxify(char *who, struct vdso_symtable *sym_rt,
 		 unsigned long vdso_rt_parked_at, size_t index,
 		 VmaEntry *vmas, size_t nr_vmas)
diff --git a/criu/pie/restorer.c b/criu/pie/restorer.c
index 7b1c129a38f9..b40bc346e279 100644
--- a/criu/pie/restorer.c
+++ b/criu/pie/restorer.c
@@ -1126,13 +1126,23 @@  long __export_restore_task(struct task_restore_args *args)
 		pr_debug("lazy-pages: uffd %d\n", args->uffd);
 	}
 
-	if (vdso_do_park(&args->vdso_sym_rt, args->vdso_rt_parked_at, vdso_rt_size))
-		goto core_restore_end;
+	if (!args->compatible_mode) {
+		/* Compatible vDSO will be mapped, not moved */
+		if (vdso_do_park(&args->vdso_sym_rt,
+				args->vdso_rt_parked_at, vdso_rt_size))
+			goto core_restore_end;
+	}
 
 	if (unmap_old_vmas((void *)args->premmapped_addr, args->premmapped_len,
 				bootstrap_start, bootstrap_len, args->task_size))
 		goto core_restore_end;
 
+	if (args->compatible_mode) {
+		/* Map compatible vdso */
+		if (vdso_map_compat(args->vdso_rt_parked_at))
+			goto core_restore_end;
+	}
+
 	/* Shift private vma-s to the left */
 	for (i = 0; i < args->vmas_n; i++) {
 		vma_entry = args->vmas + i;