[CRIU] [PATCH 4/8] vdso: share the PIE part of the vDSO proxy machinery between all architectures
Alexander Kartashov
alekskartashov at parallels.com
Mon Mar 10 01:51:24 PDT 2014
This patch splits the file arch/x86/vdso-pie.c into machine-dependent
and machine-independent parts by moving the routines vdso_fill_symtable(),
vdso_remap(), and vdso_proxify() to the file pie/vdso.c.
The ARM version of the routines is moved to the source pie/vdso-stub.c
to provide the vDSO proxy stub implementation for architectures
that don't provide the vDSO.
Signed-off-by: Alexander Kartashov <alekskartashov at parallels.com>
Cc: Cyrill Gorcunov <gorcunov at openvz.org>
---
Makefile | 4 +
arch/arm/include/asm/vdso.h | 3 -
arch/arm/vdso-pie.c | 15 ---
arch/x86/include/asm/vdso.h | 3 -
arch/x86/vdso-pie.c | 249 ---------------------------------------
include/vdso.h | 3 +
pie/Makefile | 1 +
pie/vdso-stub.c | 31 +++++
pie/vdso.c | 272 +++++++++++++++++++++++++++++++++++++++++++
9 files changed, 311 insertions(+), 270 deletions(-)
create mode 100644 pie/vdso-stub.c
create mode 100644 pie/vdso.c
diff --git a/Makefile b/Makefile
index 99ea752..7e192ad 100644
--- a/Makefile
+++ b/Makefile
@@ -180,6 +180,10 @@ PROGRAM-BUILTINS += built-in.o
$(ARCH_DIR)/vdso-pie.o: pie
$(Q) $(MAKE) $(build)=pie $(ARCH_DIR)/vdso-pie.o
PROGRAM-BUILTINS += $(ARCH_DIR)/vdso-pie.o
+pie/$(VDSO_O): pie
+ $(Q) $(MAKE) $(build)=pie pie/$(VDSO_O)
+PROGRAM-BUILTINS += pie/$(VDSO_O)
+
$(PROGRAM): $(SYSCALL-LIB) $(ARCH-LIB) $(PROGRAM-BUILTINS)
$(E) " LINK " $@
diff --git a/arch/arm/include/asm/vdso.h b/arch/arm/include/asm/vdso.h
index 56d8007..a702471 100644
--- a/arch/arm/include/asm/vdso.h
+++ b/arch/arm/include/asm/vdso.h
@@ -10,9 +10,6 @@ struct parasite_ctl;
struct vm_area_list;
extern int vdso_redirect_calls(void *base_to, void *base_from, struct vdso_symtable *to, struct vdso_symtable *from);
-extern int vdso_fill_symtable(char *mem, size_t size,struct vdso_symtable *t);
-extern int vdso_remap(char *who, unsigned long from, unsigned long to, size_t size);
-extern int vdso_proxify(char *who, struct vdso_symtable *sym_rt, VmaEntry *vma_entry, unsigned long vdso_rt_parked_at);
extern int parasite_fixup_vdso(struct parasite_ctl *ctl, pid_t pid,
struct vm_area_list *vma_area_list);
diff --git a/arch/arm/vdso-pie.c b/arch/arm/vdso-pie.c
index 1f094cb..5253d6e 100644
--- a/arch/arm/vdso-pie.c
+++ b/arch/arm/vdso-pie.c
@@ -15,18 +15,3 @@ int vdso_redirect_calls(void *base_to, void *base_from,
{
return 0;
}
-
-int vdso_fill_symtable(char *mem, size_t size, struct vdso_symtable *t)
-{
- return 0;
-}
-
-int vdso_remap(char *who, unsigned long from, unsigned long to, size_t size)
-{
- return 0;
-}
-
-int vdso_proxify(char *who, struct vdso_symtable *sym_rt, VmaEntry *vma, unsigned long vdso_rt_parked_at)
-{
- return 0;
-}
diff --git a/arch/x86/include/asm/vdso.h b/arch/x86/include/asm/vdso.h
index 56d8007..a702471 100644
--- a/arch/x86/include/asm/vdso.h
+++ b/arch/x86/include/asm/vdso.h
@@ -10,9 +10,6 @@ struct parasite_ctl;
struct vm_area_list;
extern int vdso_redirect_calls(void *base_to, void *base_from, struct vdso_symtable *to, struct vdso_symtable *from);
-extern int vdso_fill_symtable(char *mem, size_t size,struct vdso_symtable *t);
-extern int vdso_remap(char *who, unsigned long from, unsigned long to, size_t size);
-extern int vdso_proxify(char *who, struct vdso_symtable *sym_rt, VmaEntry *vma_entry, unsigned long vdso_rt_parked_at);
extern int parasite_fixup_vdso(struct parasite_ctl *ctl, pid_t pid,
struct vm_area_list *vma_area_list);
diff --git a/arch/x86/vdso-pie.c b/arch/x86/vdso-pie.c
index 64362e0..9e36a2c 100644
--- a/arch/x86/vdso-pie.c
+++ b/arch/x86/vdso-pie.c
@@ -57,253 +57,4 @@ int vdso_redirect_calls(void *base_to, void *base_from,
return 0;
}
-static unsigned int get_symbol_index(char *symbol, char *symbols[], size_t size)
-{
- unsigned int i;
-
- for (i = 0; symbol && i < size; i++) {
- if (!builtin_strcmp(symbol, symbols[i]))
- return i;
- }
-
- return VDSO_SYMBOL_MAX;
-}
-
-/* Check if pointer is out-of-bound */
-static bool __ptr_oob(void *ptr, void *start, size_t size)
-{
- void *end = (void *)((unsigned long)start + size);
- return ptr > end || ptr < start;
-}
-
-int vdso_fill_symtable(char *mem, size_t size, struct vdso_symtable *t)
-{
- Elf64_Ehdr *ehdr = (void *)mem;
- Elf64_Shdr *shdr, *shdr_strtab;
- Elf64_Shdr *shdr_dynsym;
- Elf64_Shdr *shdr_dynstr;
- Elf64_Phdr *phdr;
- Elf64_Shdr *text;
- Elf64_Sym *sym;
-
- char *section_names, *dynsymbol_names;
-
- unsigned long base = VDSO_BAD_ADDR;
- unsigned int i, j, k;
-
- /*
- * Elf header bytes. For detailed
- * description see Elf specification.
- */
- char vdso_ident[] = {
- 0x7f, 0x45, 0x4c, 0x46, 0x02, 0x01, 0x01, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- };
-
- char *vdso_x86_symbols[VDSO_SYMBOL_MAX] = {
- [VDSO_SYMBOL_GETTIMEOFDAY] = VDSO_SYMBOL_GETTIMEOFDAY_NAME,
- [VDSO_SYMBOL_GETCPU] = VDSO_SYMBOL_GETCPU_NAME,
- [VDSO_SYMBOL_CLOCK_GETTIME] = VDSO_SYMBOL_CLOCK_GETTIME_NAME,
- [VDSO_SYMBOL_TIME] = VDSO_SYMBOL_TIME_NAME,
- };
-
- BUILD_BUG_ON(sizeof(vdso_ident) != sizeof(ehdr->e_ident));
-
- pr_debug("Parsing at %lx %lx\n",
- (long)mem, (long)mem + (long)size);
-
- /*
- * Make sure it's a file we support.
- */
- if (builtin_memcmp(ehdr->e_ident, vdso_ident, sizeof(vdso_ident))) {
- pr_debug("Elf header magic mismatch\n");
- goto err;
- }
-
- /*
- * Figure out base virtual address.
- */
- phdr = (void *)&mem[ehdr->e_phoff];
- for (i = 0; i < ehdr->e_phnum; i++, phdr++) {
- if (__ptr_oob(phdr, mem, size))
- goto err;
- if (phdr->p_type == PT_LOAD) {
- base = phdr->p_vaddr;
- break;
- }
- }
- if (base != VDSO_BAD_ADDR) {
- pr_debug("Base address %lx\n", base);
- } else {
- pr_debug("No base address found\n");
- goto err;
- }
-
- /*
- * Where the section names lays.
- */
- if (ehdr->e_shstrndx == SHN_UNDEF) {
- pr_err("Section names are not found\n");
- goto err;
- }
-
- shdr = (void *)&mem[ehdr->e_shoff];
- shdr_strtab = &shdr[ehdr->e_shstrndx];
- if (__ptr_oob(shdr_strtab, mem, size))
- goto err;
-
- section_names = (void *)&mem[shdr_strtab->sh_offset];
- shdr_dynsym = shdr_dynstr = text = NULL;
-
- for (i = 0; i < ehdr->e_shnum; i++, shdr++) {
- if (__ptr_oob(shdr, mem, size))
- goto err;
- if (__ptr_oob(§ion_names[shdr->sh_name], mem, size))
- goto err;
-
-#if 0
- pr_debug("section: %2d -> %s\n",
- i, §ion_names[shdr->sh_name]);
-#endif
-
- if (shdr->sh_type == SHT_DYNSYM &&
- builtin_strcmp(§ion_names[shdr->sh_name],
- ".dynsym") == 0) {
- shdr_dynsym = shdr;
- } else if (shdr->sh_type == SHT_STRTAB &&
- builtin_strcmp(§ion_names[shdr->sh_name],
- ".dynstr") == 0) {
- shdr_dynstr = shdr;
- } else if (shdr->sh_type == SHT_PROGBITS &&
- builtin_strcmp(§ion_names[shdr->sh_name],
- ".text") == 0) {
- text = shdr;
- }
- }
-
- if (!shdr_dynsym || !shdr_dynstr || !text) {
- pr_debug("No required sections found\n");
- goto err;
- }
-
- dynsymbol_names = (void *)&mem[shdr_dynstr->sh_offset];
- if (__ptr_oob(dynsymbol_names, mem, size) ||
- __ptr_oob(shdr_dynsym, mem, size) ||
- __ptr_oob(text, mem, size))
- goto err;
-
- /*
- * Walk over global symbols and choose ones we need.
- */
- j = shdr_dynsym->sh_size / sizeof(*sym);
- sym = (void *)&mem[shdr_dynsym->sh_offset];
-
- for (i = 0; i < j; i++, sym++) {
- if (__ptr_oob(sym, mem, size))
- goto err;
-
- if (ELF64_ST_BIND(sym->st_info) != STB_GLOBAL ||
- ELF64_ST_TYPE(sym->st_info) != STT_FUNC)
- continue;
-
- if (__ptr_oob(&dynsymbol_names[sym->st_name], mem, size))
- goto err;
-
- k = get_symbol_index(&dynsymbol_names[sym->st_name],
- vdso_x86_symbols,
- ARRAY_SIZE(vdso_x86_symbols));
- if (k != VDSO_SYMBOL_MAX) {
- builtin_memcpy(t->symbols[k].name, vdso_x86_symbols[k],
- sizeof(t->symbols[k].name));
- t->symbols[k].offset = (unsigned long)sym->st_value - base;
-#if 0
- pr_debug("symbol: %#-16lx %2d %s\n",
- t->symbols[k].offset, sym->st_shndx, t->symbols[k].name);
-#endif
- }
- }
- return 0;
-err:
- return -1;
-}
-
-int vdso_remap(char *who, unsigned long from, unsigned long to, size_t size)
-{
- unsigned long addr;
-
- pr_debug("Remap %s %lx -> %lx\n", who, from, to);
-
- addr = sys_mremap(from, size, size, MREMAP_MAYMOVE | MREMAP_FIXED, to);
- if (addr != to) {
- pr_err("Unable to remap %lx -> %lx %lx\n",
- from, to, addr);
- return -1;
- }
- return 0;
-}
-
-int vdso_proxify(char *who, struct vdso_symtable *sym_rt, VmaEntry *vma, unsigned long vdso_rt_parked_at)
-{
- struct vdso_symtable s = VDSO_SYMTABLE_INIT;
- size_t size = vma_entry_len(vma);
- bool remap_rt = true;
-
- /*
- * Find symbols in dumpee vdso.
- */
- if (vdso_fill_symtable((void *)vma->start, size, &s))
- return -1;
-
- if (size == vdso_vma_size(sym_rt)) {
- int i;
-
- for (i = 0; i < ARRAY_SIZE(s.symbols); i++) {
- if (s.symbols[i].offset != sym_rt->symbols[i].offset) {
- remap_rt = false;
- break;
- }
- }
- } else
- remap_rt = false;
-
- /*
- * Easy case -- the vdso from image has same offsets and size
- * as runtime, so we simply remap runtime vdso to dumpee position
- * without generating any proxy.
- */
- if (remap_rt) {
- pr_info("Runtime vdso matches dumpee, remap inplace\n");
-
- if (sys_munmap((void *)vma->start, size)) {
- pr_err("Failed to unmap %s\n", who);
- return -1;
- }
-
- return vdso_remap(who, vdso_rt_parked_at, vma->start, size);
- }
-
- /*
- * Now complex case -- we need to proxify calls. We redirect
- * calls from dumpee vdso to runtime vdso, making dumpee
- * to operate as proxy vdso.
- */
- pr_info("Runtime vdso mismatches dumpee, generate proxy\n");
-
- if (vdso_redirect_calls((void *)vdso_rt_parked_at,
- (void *)vma->start,
- sym_rt, &s)) {
- pr_err("Failed to proxify dumpee contents\n");
- return -1;
- }
-
- /*
- * Put a special mark into runtime vdso, thus at next checkpoint
- * routine we could detect this vdso and do not dump it, since
- * it's auto-generated every new session if proxy required.
- */
- sys_mprotect((void *)vdso_rt_parked_at, vdso_vma_size(sym_rt), PROT_WRITE);
- vdso_put_mark((void *)vdso_rt_parked_at, vma->start);
- sys_mprotect((void *)vdso_rt_parked_at, vdso_vma_size(sym_rt), VDSO_PROT);
- return 0;
-}
diff --git a/include/vdso.h b/include/vdso.h
index 3f2f01f..8c748ab 100644
--- a/include/vdso.h
+++ b/include/vdso.h
@@ -110,5 +110,8 @@ static inline void vdso_put_mark(void *where, unsigned long proxy_addr)
extern struct vdso_symtable vdso_sym_rt;
extern u64 vdso_pfn;
extern int vdso_init(void);
+extern int vdso_remap(char *who, unsigned long from, unsigned long to, size_t size);
+extern int vdso_fill_symtable(char *mem, size_t size, struct vdso_symtable *t);
+extern int vdso_proxify(char *who, struct vdso_symtable *sym_rt, VmaEntry *vma_entry, unsigned long vdso_rt_parked_at);
#endif /* __CR_VDSO_H__ */
diff --git a/pie/Makefile b/pie/Makefile
index 5902804..cf59bfc 100644
--- a/pie/Makefile
+++ b/pie/Makefile
@@ -10,6 +10,7 @@ parasite-asm-e += $(ARCH_DIR)/parasite-head.o
parasite-libs-e += $(SYSCALL-LIB)
restorer-obj-y += restorer.o
+restorer-obj-y += $(VDSO_O)
restorer-obj-e += $(ARCH_DIR)/restorer.o
restorer-obj-e += $(ARCH_DIR)/vdso-pie.o
restorer-libs-e += $(SYSCALL-LIB)
diff --git a/pie/vdso-stub.c b/pie/vdso-stub.c
new file mode 100644
index 0000000..3739371
--- /dev/null
+++ b/pie/vdso-stub.c
@@ -0,0 +1,31 @@
+#include <elf.h>
+
+#include <sys/mman.h>
+
+#include "compiler.h"
+#include "vdso.h"
+#include "syscall.h"
+#include "log.h"
+
+#include "asm/string.h"
+
+
+#ifdef LOG_PREFIX
+# undef LOG_PREFIX
+#endif
+#define LOG_PREFIX "vdso: "
+
+int vdso_remap(char *who, unsigned long from, unsigned long to, size_t size)
+{
+ return 0;
+}
+
+int vdso_fill_symtable(char *mem, size_t size, struct vdso_symtable *t)
+{
+ return 0;
+}
+
+int vdso_proxify(char *who, struct vdso_symtable *sym_rt, VmaEntry *vma, unsigned long vdso_rt_parked_at)
+{
+ return 0;
+}
diff --git a/pie/vdso.c b/pie/vdso.c
new file mode 100644
index 0000000..1dcda48
--- /dev/null
+++ b/pie/vdso.c
@@ -0,0 +1,272 @@
+#include <elf.h>
+
+#include <sys/mman.h>
+
+#include "compiler.h"
+#include "vdso.h"
+#include "syscall.h"
+#include "log.h"
+#include "vma.h"
+
+#include "asm/string.h"
+
+
+#ifdef LOG_PREFIX
+# undef LOG_PREFIX
+#endif
+#define LOG_PREFIX "vdso: "
+
+int vdso_remap(char *who, unsigned long from, unsigned long to, size_t size)
+{
+ unsigned long addr;
+
+ pr_debug("Remap %s %lx -> %lx\n", who, from, to);
+
+ addr = sys_mremap(from, size, size, MREMAP_MAYMOVE | MREMAP_FIXED, to);
+ if (addr != to) {
+ pr_err("Unable to remap %lx -> %lx %lx\n",
+ from, to, addr);
+ return -1;
+ }
+
+ return 0;
+}
+
+static unsigned int get_symbol_index(char *symbol, char *symbols[], size_t size)
+{
+ unsigned int i;
+
+ for (i = 0; symbol && i < size; i++) {
+ if (!builtin_strcmp(symbol, symbols[i]))
+ return i;
+ }
+
+ return VDSO_SYMBOL_MAX;
+}
+
+
+/* Check if pointer is out-of-bound */
+static bool __ptr_oob(void *ptr, void *start, size_t size)
+{
+ void *end = (void *)((unsigned long)start + size);
+ return ptr > end || ptr < start;
+}
+
+int vdso_fill_symtable(char *mem, size_t size, struct vdso_symtable *t)
+{
+ Elf64_Ehdr *ehdr = (void *)mem;
+ Elf64_Shdr *shdr, *shdr_strtab;
+ Elf64_Shdr *shdr_dynsym;
+ Elf64_Shdr *shdr_dynstr;
+ Elf64_Phdr *phdr;
+ Elf64_Shdr *text;
+ Elf64_Sym *sym;
+
+ char *section_names, *dynsymbol_names;
+
+ unsigned long base = VDSO_BAD_ADDR;
+ unsigned int i, j, k;
+
+ /*
+ * Elf header bytes. For detailed
+ * description see Elf specification.
+ */
+ char vdso_ident[] = {
+ 0x7f, 0x45, 0x4c, 0x46, 0x02, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ };
+
+ char *vdso_x86_symbols[VDSO_SYMBOL_MAX] = {
+ [VDSO_SYMBOL_GETTIMEOFDAY] = VDSO_SYMBOL_GETTIMEOFDAY_NAME,
+ [VDSO_SYMBOL_GETCPU] = VDSO_SYMBOL_GETCPU_NAME,
+ [VDSO_SYMBOL_CLOCK_GETTIME] = VDSO_SYMBOL_CLOCK_GETTIME_NAME,
+ [VDSO_SYMBOL_TIME] = VDSO_SYMBOL_TIME_NAME,
+ };
+
+ BUILD_BUG_ON(sizeof(vdso_ident) != sizeof(ehdr->e_ident));
+
+ pr_debug("Parsing at %lx %lx\n",
+ (long)mem, (long)mem + (long)size);
+
+ /*
+ * Make sure it's a file we support.
+ */
+ if (builtin_memcmp(ehdr->e_ident, vdso_ident, sizeof(vdso_ident))) {
+ pr_debug("Elf header magic mismatch\n");
+ goto err;
+ }
+
+ /*
+ * Figure out base virtual address.
+ */
+ phdr = (void *)&mem[ehdr->e_phoff];
+ for (i = 0; i < ehdr->e_phnum; i++, phdr++) {
+ if (__ptr_oob(phdr, mem, size))
+ goto err;
+ if (phdr->p_type == PT_LOAD) {
+ base = phdr->p_vaddr;
+ break;
+ }
+ }
+ if (base != VDSO_BAD_ADDR) {
+ pr_debug("Base address %lx\n", base);
+ } else {
+ pr_debug("No base address found\n");
+ goto err;
+ }
+
+ /*
+ * Where the section names lays.
+ */
+ if (ehdr->e_shstrndx == SHN_UNDEF) {
+ pr_err("Section names are not found\n");
+ goto err;
+ }
+
+ shdr = (void *)&mem[ehdr->e_shoff];
+ shdr_strtab = &shdr[ehdr->e_shstrndx];
+ if (__ptr_oob(shdr_strtab, mem, size))
+ {
+ pr_err("shdr_strtab is outside the vDSO\n");
+ goto err;
+ }
+
+ section_names = (void *)&mem[shdr_strtab->sh_offset];
+ shdr_dynsym = shdr_dynstr = text = NULL;
+
+ for (i = 0; i < ehdr->e_shnum; i++, shdr++) {
+ if (__ptr_oob(shdr, mem, size))
+ goto err;
+ if (__ptr_oob(§ion_names[shdr->sh_name], mem, size))
+ goto err;
+
+#if 0
+ pr_debug("section: %2d -> %s\n",
+ i, §ion_names[shdr->sh_name]);
+#endif
+
+ if (shdr->sh_type == SHT_DYNSYM &&
+ builtin_strcmp(§ion_names[shdr->sh_name],
+ ".dynsym") == 0) {
+ shdr_dynsym = shdr;
+ } else if (shdr->sh_type == SHT_STRTAB &&
+ builtin_strcmp(§ion_names[shdr->sh_name],
+ ".dynstr") == 0) {
+ shdr_dynstr = shdr;
+ } else if (shdr->sh_type == SHT_PROGBITS &&
+ builtin_strcmp(§ion_names[shdr->sh_name],
+ ".text") == 0) {
+ text = shdr;
+ }
+ }
+
+ if (!shdr_dynsym || !shdr_dynstr || !text) {
+ pr_debug("No required sections found\n");
+ goto err;
+ }
+
+ dynsymbol_names = (void *)&mem[shdr_dynstr->sh_offset];
+ if (__ptr_oob(dynsymbol_names, mem, size) ||
+ __ptr_oob(shdr_dynsym, mem, size) ||
+ __ptr_oob(text, mem, size))
+ goto err;
+
+ /*
+ * Walk over global symbols and choose ones we need.
+ */
+ j = shdr_dynsym->sh_size / sizeof(*sym);
+ sym = (void *)&mem[shdr_dynsym->sh_offset];
+
+ for (i = 0; i < j; i++, sym++) {
+ if (__ptr_oob(sym, mem, size))
+ goto err;
+
+ if (ELF64_ST_BIND(sym->st_info) != STB_GLOBAL ||
+ ELF64_ST_TYPE(sym->st_info) != STT_FUNC)
+ continue;
+
+ if (__ptr_oob(&dynsymbol_names[sym->st_name], mem, size))
+ goto err;
+
+ k = get_symbol_index(&dynsymbol_names[sym->st_name],
+ vdso_x86_symbols,
+ ARRAY_SIZE(vdso_x86_symbols));
+ if (k != VDSO_SYMBOL_MAX) {
+ builtin_memcpy(t->symbols[k].name, vdso_x86_symbols[k],
+ sizeof(t->symbols[k].name));
+ t->symbols[k].offset = (unsigned long)sym->st_value - base;
+#if 0
+ pr_debug("symbol: %#-16lx %2d %s\n",
+ t->symbols[k].offset, sym->st_shndx, t->symbols[k].name);
+#endif
+ }
+ }
+ return 0;
+err:
+ return -1;
+}
+
+int vdso_proxify(char *who, struct vdso_symtable *sym_rt, VmaEntry *vma, unsigned long vdso_rt_parked_at)
+{
+ struct vdso_symtable s = VDSO_SYMTABLE_INIT;
+ size_t size = vma_entry_len(vma);
+ bool remap_rt = true;
+
+ /*
+ * Find symbols in dumpee vdso.
+ */
+ if (vdso_fill_symtable((void *)vma->start, size, &s))
+ return -1;
+
+ if (size == vdso_vma_size(sym_rt)) {
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(s.symbols); i++) {
+ if (s.symbols[i].offset != sym_rt->symbols[i].offset) {
+ remap_rt = false;
+ break;
+ }
+ }
+ } else
+ remap_rt = false;
+
+ /*
+ * Easy case -- the vdso from image has same offsets and size
+ * as runtime, so we simply remap runtime vdso to dumpee position
+ * without generating any proxy.
+ */
+ if (remap_rt) {
+ pr_info("Runtime vdso matches dumpee, remap inplace\n");
+
+ if (sys_munmap((void *)vma->start, size)) {
+ pr_err("Failed to unmap %s\n", who);
+ return -1;
+ }
+
+ return vdso_remap(who, vdso_rt_parked_at, vma->start, size);
+ }
+
+ /*
+ * Now complex case -- we need to proxify calls. We redirect
+ * calls from dumpee vdso to runtime vdso, making dumpee
+ * to operate as proxy vdso.
+ */
+ pr_info("Runtime vdso mismatches dumpee, generate proxy\n");
+
+ if (vdso_redirect_calls((void *)vdso_rt_parked_at,
+ (void *)vma->start,
+ sym_rt, &s)) {
+ pr_err("Failed to proxify dumpee contents\n");
+ return -1;
+ }
+
+ /*
+ * Put a special mark into runtime vdso, thus at next checkpoint
+ * routine we could detect this vdso and do not dump it, since
+ * it's auto-generated every new session if proxy required.
+ */
+ sys_mprotect((void *)vdso_rt_parked_at, vdso_vma_size(sym_rt), PROT_WRITE);
+ vdso_put_mark((void *)vdso_rt_parked_at, vma->start);
+ sys_mprotect((void *)vdso_rt_parked_at, vdso_vma_size(sym_rt), VDSO_PROT);
+ return 0;
+}
--
1.7.9.5
More information about the CRIU
mailing list