[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