[CRIU] [PATCH 11/11] vdso/kdat: Store symtable in kerndat_s
Dmitry Safonov
dsafonov at virtuozzo.com
Thu Jun 15 19:36:15 MSK 2017
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.
Signed-off-by: Dmitry Safonov <dsafonov at virtuozzo.com>
---
criu/include/kerndat.h | 9 ++++++++
criu/include/vdso.h | 2 ++
criu/kerndat.c | 4 ++++
criu/vdso.c | 57 +++++++++++++++++++++++++++++++++++++++++++-------
4 files changed, 65 insertions(+), 7 deletions(-)
diff --git a/criu/include/kerndat.h b/criu/include/kerndat.h
index a6dac92f97a7..7946cb9ae712 100644
--- a/criu/include/kerndat.h
+++ b/criu/include/kerndat.h
@@ -3,6 +3,9 @@
#include <stdbool.h>
#include "int.h"
+#ifdef CONFIG_VDSO
+#include "util-vdso.h"
+#endif
struct stat;
@@ -57,6 +60,12 @@ struct kerndat_s {
unsigned int sysctl_nr_open;
unsigned long files_stat_max_files;
bool has_pid_for_children_ns;
+#ifdef CONFIG_VDSO
+ struct vdso_symtable vdso_sym;
+#ifdef CONFIG_COMPAT
+ struct vdso_symtable vdso_sym_compat;
+#endif
+#endif
};
extern struct kerndat_s kdat;
diff --git a/criu/include/vdso.h b/criu/include/vdso.h
index 6a9752bd1c0b..b6110e442e04 100644
--- a/criu/include/vdso.h
+++ b/criu/include/vdso.h
@@ -15,6 +15,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 parasite_fixup_vdso(struct parasite_ctl *ctl, pid_t pid,
struct vm_area_list *vma_area_list);
@@ -28,6 +29,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 parasite_fixup_vdso(ctl, pid, vma_area_list) (0)
#endif /* CONFIG_VDSO */
diff --git a/criu/kerndat.c b/criu/kerndat.c
index 5bca4bfc92ad..593be5a5ff47 100644
--- a/criu/kerndat.c
+++ b/criu/kerndat.c
@@ -34,6 +34,7 @@
#include "netfilter.h"
#include "linux/userfaultfd.h"
#include "netfilter.h"
+#include "vdso.h"
struct kerndat_s kdat = {
};
@@ -904,6 +905,9 @@ int kerndat_init(void)
ret = kerndat_has_ns_get_parent();
if (!ret)
ret = kerndat_has_pid_for_children_ns();
+ /* Needs kdat.compat_cr filled before */
+ if (!ret)
+ ret = kerndat_vdso_fill_symtable();
kerndat_lsm();
kerndat_mmap_min_addr();
diff --git a/criu/vdso.c b/criu/vdso.c
index da3da69f4878..83f30807eea5 100644
--- a/criu/vdso.c
+++ b/criu/vdso.c
@@ -457,13 +457,6 @@ out_unmap:
pr_perror("Failed to unmap buf for compat vdso");
return ret;
}
-
-#else /* CONFIG_COMPAT */
-static int vdso_fill_compat_symtable(struct vdso_maps *native,
- struct vdso_maps *compat)
-{
- return 0;
-}
#endif /* CONFIG_COMPAT */
int vdso_init_dump(void)
@@ -481,8 +474,54 @@ int vdso_init_dump(void)
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)
{
+ 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)) {
pr_err("Failed reading self/maps for filling vdso/vvar bounds\n");
return -1;
@@ -492,11 +531,15 @@ int vdso_init_restore(void)
pr_err("Failed to fill self vdso symtable\n");
return -1;
}
+ kdat.vdso_sym = vdso_maps.sym;
+#ifdef CONFIG_COMPAT
if (vdso_fill_compat_symtable(&vdso_maps, &vdso_maps_compat)) {
pr_err("Failed to fill compat vdso symtable\n");
return -1;
}
+ kdat.vdso_sym_compat = vdso_maps_compat.sym;
+#endif
return 0;
}
--
2.12.2
More information about the CRIU
mailing list