mirror of
https://github.com/checkpoint-restore/criu.git
synced 2026-07-18 00:58:31 +00:00
vdso/kdat: Add test for preserving "[vdso]" hint after mremap()
If it does preserve, we can omit checking pagemap for dumpee or filling symtable in parasite. Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com> Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
This commit is contained in:
parent
b8f3fca489
commit
ff28da9504
4 changed files with 81 additions and 0 deletions
|
|
@ -56,6 +56,7 @@ struct kerndat_s {
|
|||
unsigned long uffd_features;
|
||||
bool has_thp_disable;
|
||||
bool can_map_vdso;
|
||||
bool vdso_hint_reliable;
|
||||
#ifdef CONFIG_VDSO
|
||||
struct vdso_symtable vdso_sym;
|
||||
#ifdef CONFIG_COMPAT
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ extern struct vdso_maps vdso_maps_compat;
|
|||
extern int vdso_init_dump(void);
|
||||
extern int vdso_init_restore(void);
|
||||
extern int kerndat_vdso_fill_symtable(void);
|
||||
extern int kerndat_vdso_preserves_hint(void);
|
||||
|
||||
extern int parasite_fixup_vdso(struct parasite_ctl *ctl, pid_t pid,
|
||||
struct vm_area_list *vma_area_list);
|
||||
|
|
@ -30,6 +31,7 @@ extern void compat_vdso_helper(struct vdso_maps *native, int pipe_fd,
|
|||
#define vdso_init_dump() (0)
|
||||
#define vdso_init_restore() (0)
|
||||
#define kerndat_vdso_fill_symtable() (0)
|
||||
#define kerndat_vdso_preserves_hint() (0)
|
||||
#define parasite_fixup_vdso(ctl, pid, vma_area_list) (0)
|
||||
|
||||
#endif /* CONFIG_VDSO */
|
||||
|
|
|
|||
|
|
@ -870,6 +870,9 @@ int kerndat_init(void)
|
|||
/* Needs kdat.compat_cr filled before */
|
||||
if (!ret)
|
||||
ret = kerndat_vdso_fill_symtable();
|
||||
/* Depends on kerndat_vdso_fill_symtable() */
|
||||
if (!ret)
|
||||
ret = kerndat_vdso_preserves_hint();
|
||||
|
||||
kerndat_lsm();
|
||||
kerndat_mmap_min_addr();
|
||||
|
|
|
|||
75
criu/vdso.c
75
criu/vdso.c
|
|
@ -621,3 +621,78 @@ int kerndat_vdso_fill_symtable(void)
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* On x86 pre-v3.16 kernels can lose "[vdso]" hint
|
||||
* in /proc/.../maps file after mremap()'ing vdso vma.
|
||||
* Depends on kerndat_vdso_fill_symtable() - assuming that
|
||||
* vdso_maps and vdso_maps_compat are filled.
|
||||
*/
|
||||
int kerndat_vdso_preserves_hint(void)
|
||||
{
|
||||
struct vdso_maps vdso_maps_after;
|
||||
int status, ret = -1;
|
||||
pid_t child;
|
||||
|
||||
kdat.vdso_hint_reliable = 0;
|
||||
|
||||
if (vdso_maps.vdso_start == VDSO_BAD_ADDR)
|
||||
return 0;
|
||||
|
||||
child = fork();
|
||||
if (child < 0) {
|
||||
pr_perror("fork() failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (child == 0) {
|
||||
unsigned long vdso_addr = vdso_maps.vdso_start;
|
||||
unsigned long vdso_size = vdso_maps.sym.vdso_size;
|
||||
void *new_addr;
|
||||
|
||||
new_addr = mmap(0, vdso_size, PROT_NONE,
|
||||
MAP_ANON | MAP_PRIVATE, -1, 0);
|
||||
if (new_addr == MAP_FAILED)
|
||||
exit(1);
|
||||
|
||||
child = getpid();
|
||||
new_addr = (void *)syscall(SYS_mremap, vdso_addr, vdso_size,
|
||||
vdso_size, MREMAP_MAYMOVE | MREMAP_FIXED, new_addr);
|
||||
if (new_addr == MAP_FAILED)
|
||||
syscall(SYS_exit, 2);
|
||||
syscall(SYS_kill, child, SIGSTOP);
|
||||
syscall(SYS_exit, 3);
|
||||
}
|
||||
|
||||
waitpid(child, &status, WUNTRACED);
|
||||
if (WIFEXITED(status)) {
|
||||
int ret = WEXITSTATUS(status);
|
||||
|
||||
pr_err("Child unexpectedly exited with %d\n", ret);
|
||||
goto out;
|
||||
} else if (WIFSIGNALED(status)) {
|
||||
int sig = WTERMSIG(status);
|
||||
|
||||
pr_err("Child unexpectedly signaled with %d: %s\n",
|
||||
sig, strsignal(sig));
|
||||
goto out;
|
||||
} else if (!WIFSTOPPED(status) || WSTOPSIG(status) != SIGSTOP) {
|
||||
pr_err("Child is unstoppable or was stopped by other means\n");
|
||||
goto out_kill;
|
||||
}
|
||||
|
||||
if (vdso_parse_maps(child, &vdso_maps_after)) {
|
||||
pr_err("Failed parsing maps for child helper\n");
|
||||
goto out_kill;
|
||||
}
|
||||
|
||||
if (vdso_maps_after.vdso_start != VDSO_BAD_ADDR)
|
||||
kdat.vdso_hint_reliable = 1;
|
||||
|
||||
ret = 0;
|
||||
out_kill:
|
||||
kill(child, SIGKILL);
|
||||
waitpid(child, &status, 0);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue