[PATCH 17/19] arm64/vdso: Migrate compat signals to user_landing

From: Dmitry Safonov
Date: Sun Nov 08 2020 - 00:18:21 EST


Generic way to track the land vma area.
As a bonus, after unmapping sigpage, kernel won't try to land on its
previous position.

Signed-off-by: Dmitry Safonov <dima@xxxxxxxxxx>
---
arch/arm64/Kconfig | 1 +
arch/arm64/kernel/signal32.c | 17 ++++++++++++-----
arch/arm64/kernel/vdso.c | 2 +-
3 files changed, 14 insertions(+), 6 deletions(-)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 7111cf335ede..56505e396253 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -38,6 +38,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_USER_LANDING
select ARCH_HAVE_ELF_PROT
select ARCH_HAVE_NMI_SAFE_CMPXCHG
select ARCH_INLINE_READ_LOCK if !PREEMPTION
diff --git a/arch/arm64/kernel/signal32.c b/arch/arm64/kernel/signal32.c
index 2f507f565c48..61d583c73be3 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->user_landing;
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_USER_LANDING)
+ 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 91c1b7c716b7..08e8f1d56d92 100644
--- a/arch/arm64/kernel/vdso.c
+++ b/arch/arm64/kernel/vdso.c
@@ -394,7 +394,7 @@ static int aarch32_sigreturn_setup(struct mm_struct *mm)
if (IS_ERR(ret))
goto out;

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

out:
return PTR_ERR_OR_ZERO(ret);
--
2.28.0