[PATCH v3 19/23] arm64/vdso: Migrate compat signals to generic vdso_base

From: Dmitry Safonov
Date: Fri Jun 11 2021 - 14:03:34 EST


Generic way to track the landing vma area.
As a bonus, after unmapping sigpage, kernel won't try to land on its
previous position (due to UNMAPPED_VDSO_BASE check instead of
context.vdso ?= 0 check).

Signed-off-by: Dmitry Safonov <dima@xxxxxxxxxx>
---
arch/arm64/Kconfig | 1 +
arch/arm64/include/asm/mmu.h | 3 ---
arch/arm64/kernel/signal32.c | 17 ++++++++++++-----
arch/arm64/kernel/vdso.c | 11 +----------
4 files changed, 14 insertions(+), 18 deletions(-)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 385ef8d8ad9b..073d6c8aa195 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -43,6 +43,7 @@ config ARM64
select ARCH_HAS_SYSCALL_WRAPPER
select ARCH_HAS_TEARDOWN_DMA_OPS if IOMMU_SUPPORT
select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
+ select ARCH_HAS_VDSO_BASE
select ARCH_HAVE_ELF_PROT
select ARCH_HAVE_NMI_SAFE_CMPXCHG
select ARCH_INLINE_READ_LOCK if !PREEMPTION
diff --git a/arch/arm64/include/asm/mmu.h b/arch/arm64/include/asm/mmu.h
index 75beffe2ee8a..434acd49dbc3 100644
--- a/arch/arm64/include/asm/mmu.h
+++ b/arch/arm64/include/asm/mmu.h
@@ -18,9 +18,6 @@

typedef struct {
atomic64_t id;
-#ifdef CONFIG_COMPAT
- void *sigpage;
-#endif
refcount_t pinned;
void *vdso;
unsigned long flags;
diff --git a/arch/arm64/kernel/signal32.c b/arch/arm64/kernel/signal32.c
index 2f507f565c48..3d2ac8062e99 100644
--- a/arch/arm64/kernel/signal32.c
+++ b/arch/arm64/kernel/signal32.c
@@ -315,7 +315,7 @@ static void __user *compat_get_sigframe(struct ksignal *ksig,
return frame;
}

-static void compat_setup_return(struct pt_regs *regs, struct k_sigaction *ka,
+static int compat_setup_return(struct pt_regs *regs, struct k_sigaction *ka,
compat_ulong_t __user *rc, void __user *frame,
int usig)
{
@@ -342,13 +342,16 @@ static void compat_setup_return(struct pt_regs *regs, struct k_sigaction *ka,
retcode = ptr_to_compat(ka->sa.sa_restorer);
} else {
/* Set up sigreturn pointer */
+ unsigned long land = (unsigned long)current->mm->vdso_base;
unsigned int idx = thumb << 1;

if (ka->sa.sa_flags & SA_SIGINFO)
idx += 3;

- retcode = (unsigned long)current->mm->context.sigpage +
- (idx << 2) + thumb;
+ if (land == UNMAPPED_VDSO_BASE)
+ return 1;
+
+ retcode = land + (idx << 2) + thumb;
}

regs->regs[0] = usig;
@@ -356,6 +359,8 @@ static void compat_setup_return(struct pt_regs *regs, struct k_sigaction *ka,
regs->compat_lr = retcode;
regs->pc = handler;
regs->pstate = spsr;
+
+ return 0;
}

static int compat_setup_sigframe(struct compat_sigframe __user *sf,
@@ -425,7 +430,8 @@ int compat_setup_rt_frame(int usig, struct ksignal *ksig,
err |= compat_setup_sigframe(&frame->sig, regs, set);

if (err == 0) {
- compat_setup_return(regs, &ksig->ka, frame->sig.retcode, frame, usig);
+ err = compat_setup_return(regs, &ksig->ka,
+ frame->sig.retcode, frame, usig);
regs->regs[1] = (compat_ulong_t)(unsigned long)&frame->info;
regs->regs[2] = (compat_ulong_t)(unsigned long)&frame->sig.uc;
}
@@ -448,7 +454,8 @@ int compat_setup_frame(int usig, struct ksignal *ksig, sigset_t *set,

err |= compat_setup_sigframe(frame, regs, set);
if (err == 0)
- compat_setup_return(regs, &ksig->ka, frame->retcode, frame, usig);
+ err = compat_setup_return(regs, &ksig->ka,
+ frame->retcode, frame, usig);

return err;
}
diff --git a/arch/arm64/kernel/vdso.c b/arch/arm64/kernel/vdso.c
index 680415e0098c..3e9dd41abee0 100644
--- a/arch/arm64/kernel/vdso.c
+++ b/arch/arm64/kernel/vdso.c
@@ -264,14 +264,6 @@ enum aarch32_map {
static struct page *aarch32_vectors_page __ro_after_init;
static struct page *aarch32_sig_page __ro_after_init;

-static int aarch32_sigpage_mremap(const struct vm_special_mapping *sm,
- struct vm_area_struct *new_vma)
-{
- current->mm->context.sigpage = (void *)new_vma->vm_start;
-
- return 0;
-}
-
static struct vm_special_mapping aarch32_vdso_maps[] = {
[AA32_MAP_VECTORS] = {
.name = "[vectors]", /* ABI */
@@ -280,7 +272,6 @@ static struct vm_special_mapping aarch32_vdso_maps[] = {
[AA32_MAP_SIGPAGE] = {
.name = "[sigpage]", /* ABI */
.pages = &aarch32_sig_page,
- .mremap = aarch32_sigpage_mremap,
},
[AA32_MAP_VVAR] = {
.name = "[vvar]",
@@ -398,7 +389,7 @@ static int aarch32_sigreturn_setup(struct mm_struct *mm)
if (IS_ERR(ret))
goto out;

- mm->context.sigpage = (void *)addr;
+ mm->vdso_base = (void __user *)addr;

out:
return PTR_ERR_OR_ZERO(ret);
--
2.31.1