Projects STRLCPY criu Commits f2504723
🤬
  • vdso/ia32: separate compat vdso helper

    As helper unmaps 64-bit vDSO blob, it can call only raw syscalls.
    Also by that reason it's code should be not instrumented with GCOV/ASAN.
    Disable instrumentation by separating it into new object and filtering
    gcov/asan cflags.
    
    Fixes: #290
    @avagin, it rarely reproduces, I failed to reproduce even once
    (with gcov, on the same env00 test, with the same linux-next)
    please, reopen #290 if you'll spot it afterward.
    
    Reported-by: Andrei Vagin <[email protected]>
    Signed-off-by: Dmitry Safonov <[email protected]>
    Signed-off-by: Andrei Vagin <[email protected]>
  • Loading...
  • Dmitry Safonov committed with Andrei Vagin 7 years ago
    f2504723
    1 parent 164e048a
Revision indexing in progress... (symbol navigation in revisions will be accurate after indexed)
  • ■ ■ ■ ■ ■
    criu/Makefile.crtools
    skipped 85 lines
    86 86  obj-y += pie-util-vdso.o
    87 87  obj-y += vdso.o
    88 88  obj-y += pie-util-vdso-elf32.o
    89  -CFLAGS_pie-util-vdso-elf32.o += -DCONFIG_VDSO_32
     89 +CFLAGS_pie-util-vdso-elf32.o += -DCONFIG_VDSO_32
     90 +obj-$(CONFIG_COMPAT) += vdso-compat.o
     91 +CFLAGS_REMOVE_vdso-compat.o += $(CFLAGS-ASAN) $(CFLAGS-GCOV)
    90 92  endif
    91 93   
    92 94  PROTOBUF_GEN := scripts/protobuf-gen.sh
    skipped 9 lines
  • ■ ■ ■ ■ ■
    criu/include/vdso.h
    skipped 17 lines
    18 18  extern int parasite_fixup_vdso(struct parasite_ctl *ctl, pid_t pid,
    19 19   struct vm_area_list *vma_area_list);
    20 20   
     21 +#ifdef CONFIG_COMPAT
     22 +void compat_vdso_helper(struct vdso_symtable *native, int pipe_fd,
     23 + int err_fd, void *vdso_buf, size_t buf_size);
     24 +#endif
     25 + 
    21 26  #else /* CONFIG_VDSO */
    22 27   
    23 28  #define vdso_init() (0)
    skipped 6 lines
  • ■ ■ ■ ■ ■ ■
    criu/vdso-compat.c
     1 +#include <sys/syscall.h>
     2 +#include <signal.h>
     3 +#include <string.h>
     4 +#include <unistd.h>
     5 + 
     6 +#include "types.h"
     7 +#include "parasite-syscall.h"
     8 +#include "parasite.h"
     9 +#include "vdso.h"
     10 + 
     11 +static void exit_on(int ret, int err_fd, char *reason)
     12 +{
     13 + if (ret) {
     14 + syscall(__NR_write, err_fd, reason, strlen(reason));
     15 + syscall(__NR_exit, ret);
     16 + }
     17 +}
     18 +/*
     19 + * Because of restrictions of ARCH_MAP_VDSO_* API, new vDSO blob
     20 + * can be mapped only if there is no vDSO blob present for a process.
     21 + * This is a helper process, it unmaps 64-bit vDSO and maps 32-bit vDSO.
     22 + * Then it copies vDSO blob to shared with CRIU mapping.
     23 + *
     24 + * The purpose is to fill compat vdso's symtable (vdso_compat_rt).
     25 + * It's an optimization to fill symtable only once at CRIU restore
     26 + * for all restored tasks.
     27 + *
     28 + * @native - 64-bit vDSO blob (for easy unmap)
     29 + * @pipe_fd - to get size of compat blob from /proc/.../maps
     30 + * @err_fd - to print error messages
     31 + * @vdso_buf, buf_size - shared with CRIU buffer
     32 + *
     33 + * WARN: This helper shouldn't call pr_err() or any syscall with
     34 + * Glibc's wrapper function - it may very likely blow up.
     35 + */
     36 +void compat_vdso_helper(struct vdso_symtable *native, int pipe_fd,
     37 + int err_fd, void *vdso_buf, size_t buf_size)
     38 +{
     39 + size_t vma_size;
     40 + void *vdso_addr;
     41 + long vdso_size;
     42 + long ret;
     43 + 
     44 + vma_size = native->vma_end - native->vma_start;
     45 + ret = syscall(__NR_munmap, native->vma_start, vma_size);
     46 + exit_on(ret, err_fd, "Error: Failed to unmap native vdso\n");
     47 + 
     48 + vma_size = native->vvar_end - native->vvar_start;
     49 + ret = syscall(__NR_munmap, native->vvar_start, vma_size);
     50 + exit_on(ret, err_fd, "Error: Failed to unmap native vvar\n");
     51 + 
     52 + ret = syscall(__NR_arch_prctl, ARCH_MAP_VDSO_32, native->vma_start);
     53 + if (ret < 0)
     54 + exit_on(ret, err_fd, "Error: ARCH_MAP_VDSO failed\n");
     55 + 
     56 + vdso_size = ret;
     57 + if (vdso_size > buf_size)
     58 + exit_on(-1, err_fd, "Error: Compatible vdso's size is bigger than reserved buf\n");
     59 + 
     60 + /* Stop so CRIU could parse smaps to find 32-bit vdso's size */
     61 + ret = syscall(__NR_kill, syscall(__NR_getpid), SIGSTOP);
     62 + exit_on(ret, err_fd, "Error: Can't stop myself with SIGSTOP (having a good time)\n");
     63 + 
     64 + ret = syscall(__NR_read, pipe_fd, &vdso_addr, sizeof(void *));
     65 + if (ret != sizeof(void *))
     66 + exit_on(-1, err_fd, "Error: Can't read size of mmaped vdso from pipe\n");
     67 + 
     68 + memcpy(vdso_buf, vdso_addr, vdso_size);
     69 + 
     70 + syscall(__NR_exit, 0);
     71 +}
     72 + 
  • ■ ■ ■ ■ ■
    criu/vdso.c
    skipped 329 lines
    330 330  }
    331 331   
    332 332  #ifdef CONFIG_COMPAT
    333  -static void exit_on(int ret, int err_fd, char *reason)
    334  -{
    335  - if (ret) {
    336  - syscall(__NR_write, err_fd, reason, strlen(reason));
    337  - syscall(__NR_exit, ret);
    338  - }
    339  -}
    340  -/*
    341  - * Because of restrictions of ARCH_MAP_VDSO_* API, new vDSO blob
    342  - * can be mapped only if there is no vDSO blob present for a process.
    343  - * This is a helper process, it unmaps 64-bit vDSO and maps 32-bit vDSO.
    344  - * Then it copies vDSO blob to shared with CRIU mapping.
    345  - *
    346  - * The purpose is to fill compat vdso's symtable (vdso_compat_rt).
    347  - * It's an optimization to fill symtable only once at CRIU restore
    348  - * for all restored tasks.
    349  - *
    350  - * @native - 64-bit vDSO blob (for easy unmap)
    351  - * @pipe_fd - to get size of compat blob from /proc/.../maps
    352  - * @err_fd - to print error messages
    353  - * @vdso_buf, buf_size - shared with CRIU buffer
    354  - *
    355  - * WARN: This helper shouldn't call pr_err() or any syscall with
    356  - * Glibc's wrapper function - it may very likely blow up.
    357  - */
    358  -static void compat_vdso_helper(struct vdso_symtable *native, int pipe_fd,
    359  - int err_fd, void *vdso_buf, size_t buf_size)
    360  -{
    361  - size_t vma_size;
    362  - void *vdso_addr;
    363  - long vdso_size;
    364  - long ret;
    365  - 
    366  - vma_size = native->vma_end - native->vma_start;
    367  - ret = syscall(__NR_munmap, native->vma_start, vma_size);
    368  - exit_on(ret, err_fd, "Error: Failed to unmap native vdso\n");
    369  - 
    370  - vma_size = native->vvar_end - native->vvar_start;
    371  - ret = syscall(__NR_munmap, native->vvar_start, vma_size);
    372  - exit_on(ret, err_fd, "Error: Failed to unmap native vvar\n");
    373  - 
    374  - ret = syscall(__NR_arch_prctl, ARCH_MAP_VDSO_32, native->vma_start);
    375  - if (ret < 0)
    376  - exit_on(ret, err_fd, "Error: ARCH_MAP_VDSO failed\n");
    377  - 
    378  - vdso_size = ret;
    379  - if (vdso_size > buf_size)
    380  - exit_on(-1, err_fd, "Error: Compatible vdso's size is bigger than reserved buf\n");
    381  - 
    382  - /* Stop so CRIU could parse smaps to find 32-bit vdso's size */
    383  - ret = syscall(__NR_kill, syscall(__NR_getpid), SIGSTOP);
    384  - exit_on(ret, err_fd, "Error: Can't stop myself with SIGSTOP (having a good time)\n");
    385  - 
    386  - ret = syscall(__NR_read, pipe_fd, &vdso_addr, sizeof(void *));
    387  - if (ret != sizeof(void *))
    388  - exit_on(-1, err_fd, "Error: Can't read size of mmaped vdso from pipe\n");
    389  - 
    390  - memcpy(vdso_buf, vdso_addr, vdso_size);
    391  - 
    392  - syscall(__NR_exit, 0);
    393  -}
    394  - 
    395 333  static int vdso_mmap_compat(struct vdso_symtable *native,
    396 334   struct vdso_symtable *compat, void *vdso_buf, size_t buf_size)
    397 335  {
    skipped 105 lines
    503 441   return ret;
    504 442  }
    505 443   
    506  -#else
     444 +#else /* CONFIG_COMPAT */
    507 445  static int vdso_fill_compat_symtable(struct vdso_symtable *native,
    508 446   struct vdso_symtable *compat)
    509 447  {
    510 448   return 0;
    511 449  }
    512  -#endif
     450 +#endif /* CONFIG_COMPAT */
    513 451   
    514 452  int vdso_init(void)
    515 453  {
    skipped 18 lines
Please wait...
Page is in error, reload to recover