diff --git a/criu/include/parasite-vdso.h b/criu/include/parasite-vdso.h index 4f25f57d3..025396319 100644 --- a/criu/include/parasite-vdso.h +++ b/criu/include/parasite-vdso.h @@ -80,14 +80,15 @@ 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_map_compat(unsigned long map_at, unsigned long park_size, + struct vdso_symtable *sym_rt); 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, bool compat_vdso); #else /* CONFIG_VDSO */ #define vdso_do_park(sym_rt, park_at, park_size) (0) -#define vdso_map_compat(map_at) (0) +#define vdso_map_compat(map_at, park_size, sym_rt) (0) #endif /* CONFIG_VDSO */ diff --git a/criu/pie/parasite-vdso.c b/criu/pie/parasite-vdso.c index a45098a19..512186c7a 100644 --- a/criu/pie/parasite-vdso.c +++ b/criu/pie/parasite-vdso.c @@ -72,18 +72,37 @@ int vdso_do_park(struct vdso_symtable *sym_rt, unsigned long park_at, unsigned l #ifndef ARCH_MAP_VDSO_32 # define ARCH_MAP_VDSO_32 0x2002 #endif -int vdso_map_compat(unsigned long map_at) +extern int vdso_fill_symtable_compat(uintptr_t mem, size_t size, + struct vdso_symtable *t); + +int vdso_map_compat(unsigned long map_at, unsigned long park_size, + struct vdso_symtable *sym_rt) { + unsigned long search_vdso; int ret; pr_debug("Mapping compatible vDSO at %lx\n", map_at); ret = sys_arch_prctl(ARCH_MAP_VDSO_32, map_at); + if (ret) + return ret; + + /* + * We could map VVAR firstly, or VDSO. + * Try to find VDSO pages in this couple of parking pages. + */ + for (search_vdso = map_at; search_vdso < map_at + park_size; + search_vdso += PAGE_SIZE) + { + ret = vdso_fill_symtable_compat(search_vdso, + map_at + park_size - search_vdso, sym_rt); + if (!ret) + return 0; + } + pr_err("Failed to parse a arch_prctl-mapped vDSO %d\n", ret); return ret; } -extern int vdso_fill_symtable_compat(uintptr_t mem, size_t size, - struct vdso_symtable *t); int __vdso_fill_symtable(uintptr_t mem, size_t size, struct vdso_symtable *t, bool compat_vdso) { @@ -93,7 +112,9 @@ int __vdso_fill_symtable(uintptr_t mem, size_t size, return vdso_fill_symtable(mem, size, t); } #else -int vdso_map_compat(unsigned long map_at) +int vdso_map_compat(unsigned long __always_unused map_at, + unsigned long __always_unused park_size, + struct vdso_symtable __always_unused *sym_rt) { return 0; } diff --git a/criu/pie/restorer.c b/criu/pie/restorer.c index 1ac49cab2..ebac5b9a4 100644 --- a/criu/pie/restorer.c +++ b/criu/pie/restorer.c @@ -1100,7 +1100,8 @@ long __export_restore_task(struct task_restore_args *args) if (args->compatible_mode) { /* Map compatible vdso */ - if (vdso_map_compat(args->vdso_rt_parked_at)) + if (vdso_map_compat(args->vdso_rt_parked_at, + vdso_rt_size, &args->vdso_sym_rt)) goto core_restore_end; }