[CRIU] [PATCH 3/8] vdso/restorer: Try best to preserve vdso during restore

Dmitry Safonov dima at arista.com
Fri Jul 26 01:01:09 MSK 2019


vdso will be used in restorer for timings in logs - try to keep it
during restore process.

Signed-off-by: Dmitry Safonov <dima at arista.com>
---
 criu/include/parasite-vdso.h |  2 +-
 criu/pie/parasite-vdso.c     |  5 ++-
 criu/pie/restorer.c          | 68 +++++++++++++++++++++++++-----------
 3 files changed, 53 insertions(+), 22 deletions(-)

diff --git a/criu/include/parasite-vdso.h b/criu/include/parasite-vdso.h
index 3cf67bbb325e..cf15d135f341 100644
--- a/criu/include/parasite-vdso.h
+++ b/criu/include/parasite-vdso.h
@@ -84,7 +84,7 @@ static inline bool is_vdso_mark(void *addr)
 extern int vdso_do_park(struct vdso_maps *rt, unsigned long park_at,
 			unsigned long park_size);
 extern int vdso_map_compat(unsigned long map_at);
-extern int vdso_proxify(struct vdso_symtable *sym_rt,
+extern int vdso_proxify(struct vdso_symtable *sym_rt, bool *added_proxy,
 			unsigned long vdso_rt_parked_at,
 			VmaEntry *vmas, size_t nr_vmas,
 			bool compat_vdso, bool force_trampolines);
diff --git a/criu/pie/parasite-vdso.c b/criu/pie/parasite-vdso.c
index 00bc2bffa29e..c4197d0cfbf0 100644
--- a/criu/pie/parasite-vdso.c
+++ b/criu/pie/parasite-vdso.c
@@ -242,7 +242,8 @@ static int add_vdso_proxy(VmaEntry *vma_vdso, VmaEntry *vma_vvar,
 	return 0;
 }
 
-int vdso_proxify(struct vdso_symtable *sym_rt, unsigned long vdso_rt_parked_at,
+int vdso_proxify(struct vdso_symtable *sym_rt, bool *added_proxy,
+		 unsigned long vdso_rt_parked_at,
 		 VmaEntry *vmas, size_t nr_vmas,
 		 bool compat_vdso, bool force_trampolines)
 {
@@ -289,11 +290,13 @@ int vdso_proxify(struct vdso_symtable *sym_rt, unsigned long vdso_rt_parked_at,
 		 vma_vvar ? (unsigned long)vma_vvar->start : VVAR_BAD_ADDR,
 		 vma_vvar ? (unsigned long)vma_vvar->end : VVAR_BAD_ADDR);
 
+	*added_proxy = false;
 	if (blobs_matches(vma_vdso, vma_vvar, &s, sym_rt) && !force_trampolines) {
 		return remap_rt_vdso(vma_vdso, vma_vvar,
 				sym_rt, vdso_rt_parked_at);
 	}
 
+	*added_proxy = true;
 	return add_vdso_proxy(vma_vdso, vma_vvar, &s, sym_rt,
 			vdso_rt_parked_at, compat_vdso);
 }
diff --git a/criu/pie/restorer.c b/criu/pie/restorer.c
index 2a7180d6a3ea..565ea0167efe 100644
--- a/criu/pie/restorer.c
+++ b/criu/pie/restorer.c
@@ -1215,32 +1215,37 @@ static int wait_zombies(struct task_restore_args *task_args)
 	return 0;
 }
 
-static bool vdso_unmapped(struct task_restore_args *args)
+static bool can_restore_vdso(struct task_restore_args *args)
 {
+	struct vdso_maps *rt = &args->vdso_maps_rt;
+	bool had_vdso = false, had_vvar = false;
 	unsigned int i;
 
-	/* Don't park rt-vdso or rt-vvar if dumpee doesn't have them */
 	for (i = 0; i < args->vmas_n; i++) {
 		VmaEntry *vma = &args->vmas[i];
 
-		if (vma_entry_is(vma, VMA_AREA_VDSO) ||
-				vma_entry_is(vma, VMA_AREA_VVAR))
-			return false;
+		if (vma_entry_is(vma, VMA_AREA_VDSO))
+			had_vdso = true;
+		if (vma_entry_is(vma, VMA_AREA_VVAR))
+			had_vvar = true;
 	}
 
-	return true;
-}
-
-static bool vdso_needs_parking(struct task_restore_args *args)
-{
-	/* Compatible vDSO will be mapped, not moved */
-	if (args->compatible_mode)
+	if (had_vdso && (rt->vdso_start == VDSO_BAD_ADDR)) {
+		pr_err("Task had vdso, restorer doesn't\n");
 		return false;
+	}
 
-	if (args->can_map_vdso)
-		return false;
+	/*
+	 * There is a use-case for restoring vvar alone: valgrind (see #488).
+	 * On the other side, we expect that vvar is touched by application
+	 * only from vdso. So, we can put a stale page and proceed restore
+	 * if kernel doesn't provide vvar [but provides vdso, if needede.
+	 * Just warn aloud that we don't like it.
+	 */
+	if (had_vvar && (rt->vvar_start == VVAR_BAD_ADDR))
+		pr_warn("Can't restore vvar - continuing regardless\n");
 
-	return !vdso_unmapped(args);
+	return true;
 }
 
 static inline int restore_child_subreaper(int child_subreaper)
@@ -1279,6 +1284,7 @@ long __export_restore_task(struct task_restore_args *args)
 	k_rtsigset_t to_block;
 	pid_t my_pid = sys_getpid();
 	rt_sigaction_t act;
+	bool has_vdso_proxy;
 
 	bootstrap_start = args->bootstrap_start;
 	bootstrap_len	= args->bootstrap_len;
@@ -1325,7 +1331,21 @@ long __export_restore_task(struct task_restore_args *args)
 		pr_debug("lazy-pages: uffd %d\n", args->uffd);
 	}
 
-	if (vdso_needs_parking(args)) {
+	/*
+	 * Park vdso/vvar in a safe place if architecture doesn't support
+	 * mapping them with arch_prctl().
+	 * Always preserve/map rt-vdso pair if it's possible, regardless
+	 * it's presence in original task: vdso will be used for fast
+	 * getttimeofday() in restorer's log timings.
+	 */
+	if (!args->can_map_vdso) {
+		/* It's already checked in kdat, but let's check again */
+		if (args->compatible_mode) {
+			pr_err("Compatible mode without vdso map support\n");
+			goto core_restore_end;
+		}
+		if (!can_restore_vdso(args))
+			goto core_restore_end;
 		if (vdso_do_park(&args->vdso_maps_rt,
 				args->vdso_rt_parked_at, vdso_rt_size))
 			goto core_restore_end;
@@ -1336,9 +1356,12 @@ long __export_restore_task(struct task_restore_args *args)
 		goto core_restore_end;
 
 	/* Map vdso that wasn't parked */
-	if (!vdso_unmapped(args) && args->can_map_vdso) {
-		if (arch_map_vdso(args->vdso_rt_parked_at,
-				args->compatible_mode) < 0) {
+	if (args->can_map_vdso) {
+		int err = arch_map_vdso(args->vdso_rt_parked_at,
+					args->compatible_mode);
+
+		if (err < 0) {
+			pr_err("Failed to map vdso %d\n", err);
 			goto core_restore_end;
 		}
 	}
@@ -1473,11 +1496,16 @@ long __export_restore_task(struct task_restore_args *args)
 	/*
 	 * Proxify vDSO.
 	 */
-	if (vdso_proxify(&args->vdso_maps_rt.sym, args->vdso_rt_parked_at,
+	if (vdso_proxify(&args->vdso_maps_rt.sym, &has_vdso_proxy,
+		     args->vdso_rt_parked_at,
 		     args->vmas, args->vmas_n, args->compatible_mode,
 		     fault_injected(FI_VDSO_TRAMPOLINES)))
 		goto core_restore_end;
 
+	/* unmap rt-vdso with restorer blob after restore's finished */
+	if (!has_vdso_proxy)
+		vdso_rt_size = 0;
+
 	/*
 	 * Walk though all VMAs again to drop PROT_WRITE
 	 * if it was not there.
-- 
2.22.0



More information about the CRIU mailing list