[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