[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