[CRIU] [PATCHv2 13/22] vdso: fill compat symtab in CRIU

Dmitry Safonov dsafonov at virtuozzo.com
Wed Dec 7 09:56:28 PST 2016


The next patch will remove filling in restorer rt symtable
for compat tasks.

Signed-off-by: Dmitry Safonov <dsafonov at virtuozzo.com>
---
 criu/Makefile.crtools      |  2 ++
 criu/include/util-vdso.h   |  7 +++++
 criu/pie-util-vdso-elf32.c |  1 +
 criu/pie/parasite-vdso.c   |  6 -----
 criu/vdso.c                | 66 ++++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 76 insertions(+), 6 deletions(-)
 create mode 120000 criu/pie-util-vdso-elf32.c

diff --git a/criu/Makefile.crtools b/criu/Makefile.crtools
index 8c5b0ce081e1..2e403f340296 100644
--- a/criu/Makefile.crtools
+++ b/criu/Makefile.crtools
@@ -84,6 +84,8 @@ obj-y			+= uffd.o
 ifeq ($(VDSO),y)
 obj-y			+= pie-util-vdso.o
 obj-y			+= vdso.o
+obj-y			+= pie-util-vdso-elf32.o
+CFLAGS_pie-util-vdso-elf32.o      += -DCONFIG_VDSO_32
 endif
 
 PROTOBUF_GEN := $(SRC_DIR)/scripts/protobuf-gen.sh
diff --git a/criu/include/util-vdso.h b/criu/include/util-vdso.h
index f4ee7fef6a0c..642cee737ec5 100644
--- a/criu/include/util-vdso.h
+++ b/criu/include/util-vdso.h
@@ -93,5 +93,12 @@ static inline unsigned long vvar_vma_size(struct vdso_symtable *t)
 #endif
 
 extern int vdso_fill_symtable(uintptr_t mem, size_t size, struct vdso_symtable *t);
+#if defined(CONFIG_X86_64) && defined(CONFIG_COMPAT)
+#ifndef ARCH_MAP_VDSO_32
+# define ARCH_MAP_VDSO_32	0x2002
+#endif
+extern int vdso_fill_symtable_compat(uintptr_t mem, size_t size,
+		struct vdso_symtable *t);
+#endif
 
 #endif /* __CR_UTIL_VDSO_H__ */
diff --git a/criu/pie-util-vdso-elf32.c b/criu/pie-util-vdso-elf32.c
new file mode 120000
index 000000000000..961bb1d376b5
--- /dev/null
+++ b/criu/pie-util-vdso-elf32.c
@@ -0,0 +1 @@
+pie/util-vdso-elf32.c
\ No newline at end of file
diff --git a/criu/pie/parasite-vdso.c b/criu/pie/parasite-vdso.c
index a05645f876e2..a88018da05fe 100644
--- a/criu/pie/parasite-vdso.c
+++ b/criu/pie/parasite-vdso.c
@@ -69,12 +69,6 @@ int vdso_do_park(struct vdso_symtable *sym_rt, unsigned long park_at, unsigned l
 }
 
 #if defined(CONFIG_X86_64) && defined(CONFIG_COMPAT)
-#ifndef ARCH_MAP_VDSO_32
-# define ARCH_MAP_VDSO_32	0x2002
-#endif
-extern int vdso_fill_symtable_compat(uintptr_t mem, size_t size,
-		struct vdso_symtable *t);
-
 int vdso_map_compat(unsigned long map_at, unsigned long *park_size,
 		struct vdso_symtable *sym_rt)
 {
diff --git a/criu/vdso.c b/criu/vdso.c
index 232c2045e8bf..014d48c28a04 100644
--- a/criu/vdso.c
+++ b/criu/vdso.c
@@ -8,6 +8,7 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <sys/mman.h>
+#include <sys/wait.h>
 
 #include "types.h"
 #include "parasite-syscall.h"
@@ -20,6 +21,7 @@
 #include "mem.h"
 #include "vma.h"
 #include <compel/compel.h>
+#include <compel/plugins/std/syscall.h>
 
 #ifdef LOG_PREFIX
 # undef LOG_PREFIX
@@ -28,6 +30,7 @@
 
 struct vdso_symtable vdso_sym_rt = VDSO_SYMTABLE_INIT;
 u64 vdso_pfn = VDSO_BAD_PFN;
+struct vdso_symtable vdso_compat_rt = VDSO_SYMTABLE_INIT;
 /*
  * The VMAs list might have proxy vdso/vvar areas left
  * from previous dump/restore cycle so we need to detect
@@ -325,10 +328,73 @@ static int vdso_fill_self_symtable(struct vdso_symtable *s)
 	return 0;
 }
 
+static int vdso_fill_compat_symtable(struct vdso_symtable *native,
+		struct vdso_symtable *compat)
+{
+#ifdef CONFIG_COMPAT
+	pid_t pid;
+	int status, ret = -1;
+
+	pid = fork();
+	if (pid == 0) {
+		size_t vma_size = native->vma_end - native->vma_start;
+
+		if (syscall(__NR_munmap, native->vma_start, vma_size))
+			syscall(__NR_exit, 1);
+		vma_size = native->vvar_end - native->vvar_start;
+		if (syscall(__NR_munmap, native->vvar_start, vma_size))
+			syscall(__NR_exit, 2);
+
+		if (syscall(__NR_arch_prctl, ARCH_MAP_VDSO_32, native->vma_start) < 0)
+			syscall(__NR_exit, 3);
+
+		syscall(__NR_kill, syscall(__NR_getpid), SIGSTOP);
+		/* this helper should be killed at this point */
+		BUG();
+	}
+
+	waitpid(pid, &status, WUNTRACED);
+
+	if (WIFEXITED(status)) {
+		pr_err("Compat vdso helper exited with %d\n",
+				WEXITSTATUS(status));
+		goto out_kill;
+	}
+
+	if (!WIFSTOPPED(status)) {
+		pr_err("Compat vdso helper isn't stopped\n");
+		goto out_kill;
+	}
+
+	if (vdso_parse_maps(pid, compat))
+		goto out_kill;
+
+	if (vdso_fill_symtable_compat(compat->vma_start,
+				compat->vma_end - compat->vma_start, compat))
+		goto out_kill;
+
+	if (validate_vdso_addr(compat))
+		goto out_kill;
+
+	pr_debug("compat [vdso] %lx-%lx [vvar] %lx-%lx\n",
+		 compat->vma_start, compat->vma_end,
+		 compat->vvar_start, compat->vvar_end);
+	ret = 0;
+
+out_kill:
+	kill(pid, SIGKILL);
+	return ret;
+#else
+	return 0;
+#endif
+}
+
 int vdso_init(void)
 {
 	if (vdso_fill_self_symtable(&vdso_sym_rt))
 		return -1;
+	if (vdso_fill_compat_symtable(&vdso_sym_rt, &vdso_compat_rt))
+		return -1;
 
 	if (kdat.pmap != PM_FULL)
 		pr_info("VDSO detection turned off\n");
-- 
2.10.2



More information about the CRIU mailing list