Commit 7ad5df9e authored by Dmitry Safonov's avatar Dmitry Safonov Committed by Andrei Vagin

vdso/kdat: Store symtable in kerndat_s

Don't need to parse vdso symtable each restore - it's boot-persistent,
so move it into criu.kdat file on tmpfs.
That will also remove syscalls made for filling compat vdso symtable
by compat vdso helper.
Reviewed-by: 's avatarCyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: 's avatarDmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: 's avatarAndrei Vagin <avagin@virtuozzo.com>
parent 78402658
...@@ -5,6 +5,9 @@ ...@@ -5,6 +5,9 @@
#include "int.h" #include "int.h"
#include "config.h" #include "config.h"
#ifdef CONFIG_VDSO
#include "util-vdso.h"
#endif
struct stat; struct stat;
...@@ -52,6 +55,12 @@ struct kerndat_s { ...@@ -52,6 +55,12 @@ struct kerndat_s {
bool has_uffd; bool has_uffd;
unsigned long uffd_features; unsigned long uffd_features;
bool has_thp_disable; bool has_thp_disable;
#ifdef CONFIG_VDSO
struct vdso_symtable vdso_sym;
#ifdef CONFIG_COMPAT
struct vdso_symtable vdso_sym_compat;
#endif
#endif
}; };
extern struct kerndat_s kdat; extern struct kerndat_s kdat;
......
...@@ -15,6 +15,7 @@ extern struct vdso_maps vdso_maps_compat; ...@@ -15,6 +15,7 @@ extern struct vdso_maps vdso_maps_compat;
extern int vdso_init_dump(void); extern int vdso_init_dump(void);
extern int vdso_init_restore(void); extern int vdso_init_restore(void);
extern int kerndat_vdso_fill_symtable(void);
extern int parasite_fixup_vdso(struct parasite_ctl *ctl, pid_t pid, extern int parasite_fixup_vdso(struct parasite_ctl *ctl, pid_t pid,
struct vm_area_list *vma_area_list); struct vm_area_list *vma_area_list);
...@@ -28,6 +29,7 @@ extern void compat_vdso_helper(struct vdso_maps *native, int pipe_fd, ...@@ -28,6 +29,7 @@ extern void compat_vdso_helper(struct vdso_maps *native, int pipe_fd,
#define vdso_init_dump() (0) #define vdso_init_dump() (0)
#define vdso_init_restore() (0) #define vdso_init_restore() (0)
#define kerndat_vdso_fill_symtable() (0)
#define parasite_fixup_vdso(ctl, pid, vma_area_list) (0) #define parasite_fixup_vdso(ctl, pid, vma_area_list) (0)
#endif /* CONFIG_VDSO */ #endif /* CONFIG_VDSO */
......
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
#include "linux/userfaultfd.h" #include "linux/userfaultfd.h"
#include "prctl.h" #include "prctl.h"
#include "uffd.h" #include "uffd.h"
#include "vdso.h"
struct kerndat_s kdat = { struct kerndat_s kdat = {
}; };
...@@ -861,6 +862,9 @@ int kerndat_init(void) ...@@ -861,6 +862,9 @@ int kerndat_init(void)
ret = kerndat_uffd(); ret = kerndat_uffd();
if (!ret) if (!ret)
ret = kerndat_has_thp_disable(); ret = kerndat_has_thp_disable();
/* Needs kdat.compat_cr filled before */
if (!ret)
ret = kerndat_vdso_fill_symtable();
kerndat_lsm(); kerndat_lsm();
kerndat_mmap_min_addr(); kerndat_mmap_min_addr();
......
...@@ -457,13 +457,6 @@ out_unmap: ...@@ -457,13 +457,6 @@ out_unmap:
pr_perror("Failed to unmap buf for compat vdso"); pr_perror("Failed to unmap buf for compat vdso");
return ret; return ret;
} }
#else /* CONFIG_COMPAT */
static int vdso_fill_compat_symtable(struct vdso_maps *native,
struct vdso_maps *compat)
{
return 0;
}
#endif /* CONFIG_COMPAT */ #endif /* CONFIG_COMPAT */
int vdso_init_dump(void) int vdso_init_dump(void)
...@@ -481,7 +474,53 @@ int vdso_init_dump(void) ...@@ -481,7 +474,53 @@ int vdso_init_dump(void)
return 0; 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
* not parked as run-time vdso in restorer, but mapped with
* arch_prlctl(MAP_VDSO_32) API.
* By that reason we verify only native sizes.
*/
static int is_kdat_vdso_sym_valid(void)
{
if (vdso_maps.sym.vdso_size != kdat.vdso_sym.vdso_size)
return false;
if (vdso_maps.sym.vvar_size != kdat.vdso_sym.vvar_size)
return false;
return true;
}
int vdso_init_restore(void) int vdso_init_restore(void)
{
if (kdat.vdso_sym.vdso_size == VDSO_BAD_SIZE) {
pr_err("Kdat has empty vdso symtable\n");
return -1;
}
/* Already filled vdso_maps during kdat test */
if (vdso_maps.vdso_start != VDSO_BAD_ADDR)
return 0;
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;
}
vdso_maps.sym = kdat.vdso_sym;
#ifdef CONFIG_COMPAT
vdso_maps_compat.sym = kdat.vdso_sym_compat;
#endif
return 0;
}
int kerndat_vdso_fill_symtable(void)
{ {
if (vdso_parse_maps(PROC_SELF, &vdso_maps)) { if (vdso_parse_maps(PROC_SELF, &vdso_maps)) {
pr_err("Failed reading self/maps for filling vdso/vvar bounds\n"); pr_err("Failed reading self/maps for filling vdso/vvar bounds\n");
...@@ -492,11 +531,15 @@ int vdso_init_restore(void) ...@@ -492,11 +531,15 @@ int vdso_init_restore(void)
pr_err("Failed to fill self vdso symtable\n"); pr_err("Failed to fill self vdso symtable\n");
return -1; return -1;
} }
kdat.vdso_sym = vdso_maps.sym;
#ifdef CONFIG_COMPAT
if (vdso_fill_compat_symtable(&vdso_maps, &vdso_maps_compat)) { if (vdso_fill_compat_symtable(&vdso_maps, &vdso_maps_compat)) {
pr_err("Failed to fill compat vdso symtable\n"); pr_err("Failed to fill compat vdso symtable\n");
return -1; return -1;
} }
kdat.vdso_sym_compat = vdso_maps_compat.sym;
#endif
return 0; return 0;
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment