Skip to content

Commit

Permalink
ARM: 8683/1: ARM32: Support mremap() for sigpage/vDSO
Browse files Browse the repository at this point in the history
CRIU restores application mappings on the same place where they
were before Checkpoint. That means, that we need to move vDSO
and sigpage during restore on exactly the same place where
they were before C/R.

Make mremap() code update mm->context.{sigpage,vdso} pointers
during VMA move. Sigpage is used for landing after handling
a signal - if the pointer is not updated during moving, the
application might crash on any signal after mremap().

vDSO pointer on ARM32 is used only for setting auxv at this moment,
update it during mremap() in case of future usage.

Without those updates, current work of CRIU on ARM32 is not reliable.
Historically, we error Checkpointing if we find vDSO page on ARM32
and suggest user to disable CONFIG_VDSO.
But that's not correct - it goes from x86 where signal processing
is ended in vDSO blob. For arm32 it's sigpage, which is not disabled
with `CONFIG_VDSO=n'.

Looks like C/R was working by luck - because userspace on ARM32 at
this moment always sets SA_RESTORER.

Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Acked-by: Andy Lutomirski <luto@amacapital.net>
Cc: linux-arm-kernel@lists.infradead.org
Cc: Will Deacon <will.deacon@arm.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Cyrill Gorcunov <gorcunov@openvz.org>
Cc: Pavel Emelyanov <xemul@virtuozzo.com>
Cc: Christopher Covington <cov@codeaurora.org>
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
  • Loading branch information
0x7f454c46 authored and Russell King committed Jun 21, 2017
1 parent 2d618fe commit 280e87e
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 3 deletions.
8 changes: 8 additions & 0 deletions arch/arm/kernel/process.c
Original file line number Diff line number Diff line change
Expand Up @@ -404,9 +404,17 @@ static unsigned long sigpage_addr(const struct mm_struct *mm,
static struct page *signal_page;
extern struct page *get_signal_page(void);

static int sigpage_mremap(const struct vm_special_mapping *sm,
struct vm_area_struct *new_vma)
{
current->mm->context.sigpage = new_vma->vm_start;
return 0;
}

static const struct vm_special_mapping sigpage_mapping = {
.name = "[sigpage]",
.pages = &signal_page,
.mremap = sigpage_mremap,
};

int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
Expand Down
18 changes: 18 additions & 0 deletions arch/arm/kernel/vdso.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,26 @@ static const struct vm_special_mapping vdso_data_mapping = {
.pages = &vdso_data_page,
};

static int vdso_mremap(const struct vm_special_mapping *sm,
struct vm_area_struct *new_vma)
{
unsigned long new_size = new_vma->vm_end - new_vma->vm_start;
unsigned long vdso_size;

/* without VVAR page */
vdso_size = (vdso_total_pages - 1) << PAGE_SHIFT;

if (vdso_size != new_size)
return -EINVAL;

current->mm->context.vdso = new_vma->vm_start;

return 0;
}

static struct vm_special_mapping vdso_text_mapping __ro_after_init = {
.name = "[vdso]",
.mremap = vdso_mremap,
};

struct elfinfo {
Expand Down
3 changes: 0 additions & 3 deletions arch/x86/entry/vdso/vma.c
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,6 @@ static int vdso_mremap(const struct vm_special_mapping *sm,
if (image->size != new_size)
return -EINVAL;

if (WARN_ON_ONCE(current->mm != new_vma->vm_mm))
return -EFAULT;

vdso_fix_landing(image, new_vma);
current->mm->context.vdso = (void __user *)new_vma->vm_start;

Expand Down
4 changes: 4 additions & 0 deletions mm/mmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -3152,8 +3152,12 @@ static int special_mapping_mremap(struct vm_area_struct *new_vma)
{
struct vm_special_mapping *sm = new_vma->vm_private_data;

if (WARN_ON_ONCE(current->mm != new_vma->vm_mm))
return -EFAULT;

if (sm->mremap)
return sm->mremap(sm, new_vma);

return 0;
}

Expand Down

0 comments on commit 280e87e

Please sign in to comment.