mirror of
https://github.com/checkpoint-restore/criu.git
synced 2026-07-27 12:04:24 +00:00
vdso: Repair !CONFIG_VDSO
Apparently, C/R is broken when CONFIG_VDSO is not set.
Probably, I've broken it while adding arm vdso support.
Or maybe some commits after.
Repair it by adding checks into vdso_init_dump(), vdso_init_restore().
Also, don't try handling vDSO in restorer if it wasn't present in
parent. And prevent summing VDSO_BAD_SIZE to {vdso,vvar}_rt_size.
Reported-by: Adrian Reber <areber@redhat.com>
Signed-off-by: Dmitry Safonov <dima@arista.com>
This commit is contained in:
parent
0022c28468
commit
a96a7ed87f
4 changed files with 50 additions and 21 deletions
|
|
@ -3373,10 +3373,13 @@ static int sigreturn_restore(pid_t pid, struct task_restore_args *task_args, uns
|
|||
vdso_maps_rt = vdso_maps;
|
||||
/*
|
||||
* Figure out how much memory runtime vdso and vvar will need.
|
||||
* Check if vDSO or VVAR is not provided by kernel.
|
||||
*/
|
||||
vdso_rt_size = vdso_maps_rt.sym.vdso_size;
|
||||
if (vdso_rt_size && vdso_maps_rt.sym.vvar_size)
|
||||
vdso_rt_size += ALIGN(vdso_maps_rt.sym.vvar_size, PAGE_SIZE);
|
||||
if (vdso_maps_rt.sym.vdso_size != VDSO_BAD_SIZE) {
|
||||
vdso_rt_size = vdso_maps_rt.sym.vdso_size;
|
||||
if (vdso_maps_rt.sym.vvar_size != VVAR_BAD_SIZE)
|
||||
vdso_rt_size += ALIGN(vdso_maps_rt.sym.vvar_size, PAGE_SIZE);
|
||||
}
|
||||
task_args->bootstrap_len += vdso_rt_size;
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -292,6 +292,18 @@ int vdso_proxify(struct vdso_maps *rt, bool *added_proxy,
|
|||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* We could still do something about it here..
|
||||
* 1. Hope that vDSO from images still works (might not be the case).
|
||||
* 2. Try to map vDSO.
|
||||
* But, hopefully no one intends to migrate application that uses
|
||||
* vDSO to a dut where kernel doesn't provide it.
|
||||
*/
|
||||
if (!vdso_is_present(rt)) {
|
||||
pr_err("vDSO isn't provided by kernel, but exists in images\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* vDSO mark overwrites Elf program header of proxy vDSO thus
|
||||
* it must never ever be greater in size.
|
||||
|
|
|
|||
|
|
@ -1454,7 +1454,7 @@ long __export_restore_task(struct task_restore_args *args)
|
|||
* it's presence in original task: vdso will be used for fast
|
||||
* getttimeofday() in restorer's log timings.
|
||||
*/
|
||||
if (!args->can_map_vdso) {
|
||||
if (!args->can_map_vdso && vdso_is_present(&args->vdso_maps_rt)) {
|
||||
/* It's already checked in kdat, but let's check again */
|
||||
if (args->compatible_mode) {
|
||||
pr_err("Compatible mode without vdso map support\n");
|
||||
|
|
|
|||
48
criu/vdso.c
48
criu/vdso.c
|
|
@ -275,6 +275,10 @@ int parasite_fixup_vdso(struct parasite_ctl *ctl, pid_t pid,
|
|||
struct vma_area *vma;
|
||||
int fd = -1;
|
||||
|
||||
/* vDSO is not provided by kernel */
|
||||
if (kdat.vdso_sym.vdso_size == VDSO_BAD_SIZE)
|
||||
return 0;
|
||||
|
||||
vcheck = get_vdso_check_type(ctl);
|
||||
if (vcheck == VDSO_CHECK_PFN) {
|
||||
BUG_ON(vdso_pfn == VDSO_BAD_PFN);
|
||||
|
|
@ -534,21 +538,6 @@ out_unmap:
|
|||
}
|
||||
#endif /* CONFIG_COMPAT */
|
||||
|
||||
int vdso_init_dump(void)
|
||||
{
|
||||
if (vdso_parse_maps(PROC_SELF, &vdso_maps)) {
|
||||
pr_err("Failed reading self/maps for filling vdso/vvar bounds\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (kdat.pmap != PM_FULL)
|
||||
pr_info("VDSO detection turned off\n");
|
||||
else if (vaddr_to_pfn(-1, vdso_maps.vdso_start, &vdso_pfn))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check vdso/vvar sized read from maps to kdat values.
|
||||
* We do not read /proc/self/maps for compatible vdso as it's
|
||||
|
|
@ -566,11 +555,36 @@ static int is_kdat_vdso_sym_valid(void)
|
|||
return true;
|
||||
}
|
||||
|
||||
int vdso_init_dump(void)
|
||||
{
|
||||
if (vdso_parse_maps(PROC_SELF, &vdso_maps)) {
|
||||
pr_err("Failed reading self/maps for filling vdso/vvar bounds\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!is_kdat_vdso_sym_valid()) {
|
||||
pr_err("Kdat sizes of vdso/vvar differ to maps file \n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (kdat.vdso_sym.vdso_size == VDSO_BAD_SIZE) {
|
||||
pr_debug("Kdat has empty vdso symtable - probably CONFIG_VDSO is not set\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (kdat.pmap != PM_FULL)
|
||||
pr_info("VDSO detection turned off\n");
|
||||
else if (vaddr_to_pfn(-1, vdso_maps.vdso_start, &vdso_pfn))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int vdso_init_restore(void)
|
||||
{
|
||||
if (kdat.vdso_sym.vdso_size == VDSO_BAD_SIZE) {
|
||||
pr_err("Kdat has empty vdso symtable\n");
|
||||
return -1;
|
||||
pr_debug("Kdat has empty vdso symtable - probably CONFIG_VDSO is not set\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Already filled vdso_maps during kdat test */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue