[PATCH v3 20/23] arm64/vdso: Migrate native signals to generic vdso_base

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


Generic way to track the land vma area.
As a bonus, after unmapping vdso, 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/include/asm/mmu.h | 1 -
arch/arm64/kernel/signal.c | 10 +++++++---
arch/arm64/kernel/vdso.c | 15 ++++++---------
3 files changed, 13 insertions(+), 13 deletions(-)

diff --git a/arch/arm64/include/asm/mmu.h b/arch/arm64/include/asm/mmu.h
index 434acd49dbc3..4432a2809e0d 100644
--- a/arch/arm64/include/asm/mmu.h
+++ b/arch/arm64/include/asm/mmu.h
@@ -19,7 +19,6 @@
typedef struct {
atomic64_t id;
refcount_t pinned;
- void *vdso;
unsigned long flags;
} mm_context_t;

diff --git a/arch/arm64/kernel/signal.c b/arch/arm64/kernel/signal.c
index 6237486ff6bb..5f6a8c0abc4c 100644
--- a/arch/arm64/kernel/signal.c
+++ b/arch/arm64/kernel/signal.c
@@ -723,9 +723,10 @@ static int get_sigframe(struct rt_sigframe_user_layout *user,
return 0;
}

-static void setup_return(struct pt_regs *regs, struct k_sigaction *ka,
+static int setup_return(struct pt_regs *regs, struct k_sigaction *ka,
struct rt_sigframe_user_layout *user, int usig)
{
+ unsigned long land = (unsigned long)current->mm->vdso_base;
__sigrestore_t sigtramp;

regs->regs[0] = usig;
@@ -754,10 +755,13 @@ static void setup_return(struct pt_regs *regs, struct k_sigaction *ka,

if (ka->sa.sa_flags & SA_RESTORER)
sigtramp = ka->sa.sa_restorer;
+ else if (land != UNMAPPED_VDSO_BASE)
+ sigtramp = VDSO_SYMBOL(land, sigtramp);
else
- sigtramp = VDSO_SYMBOL(current->mm->context.vdso, sigtramp);
+ return 1;

regs->regs[30] = (unsigned long)sigtramp;
+ return 0;
}

static int setup_rt_frame(int usig, struct ksignal *ksig, sigset_t *set,
@@ -780,7 +784,7 @@ static int setup_rt_frame(int usig, struct ksignal *ksig, sigset_t *set,
err |= __save_altstack(&frame->uc.uc_stack, regs->sp);
err |= setup_sigframe(&user, regs, set);
if (err == 0) {
- setup_return(regs, &ksig->ka, &user, usig);
+ err = setup_return(regs, &ksig->ka, &user, usig);
if (ksig->ka.sa.sa_flags & SA_SIGINFO) {
err |= copy_siginfo_to_user(&frame->info, &ksig->info);
regs->regs[1] = (unsigned long)&frame->info;
diff --git a/arch/arm64/kernel/vdso.c b/arch/arm64/kernel/vdso.c
index 3e9dd41abee0..4af29f89be37 100644
--- a/arch/arm64/kernel/vdso.c
+++ b/arch/arm64/kernel/vdso.c
@@ -78,12 +78,6 @@ static union {
} vdso_data_store __page_aligned_data;
struct vdso_data *vdso_data = vdso_data_store.data;

-static void vdso_mremap(const struct vm_special_mapping *sm,
- struct vm_area_struct *new_vma)
-{
- current->mm->context.vdso = (void *)new_vma->vm_start;
-}
-
static int __init __vdso_init(enum vdso_abi abi)
{
int i;
@@ -244,7 +238,12 @@ static int __setup_additional_pages(enum vdso_abi abi,
if (IS_ERR(ret))
return PTR_ERR(ret);

- mm->context.vdso = (void *)vdso_base;
+ /*
+ * 32-bit ABI is to land on sigpage (see aarch32_sigreturn_setup()),
+ * 64-bit on vDSO.
+ */
+ if (abi == VDSO_ABI_AA64)
+ mm->vdso_base = (void __user *)vdso_base;
*sysinfo_ehdr = vdso_base;

return 0;
@@ -279,7 +278,6 @@ static struct vm_special_mapping aarch32_vdso_maps[] = {
},
[AA32_MAP_VDSO] = {
.name = "[vdso]",
- .mremap = vdso_mremap,
},
};

@@ -426,7 +424,6 @@ static struct vm_special_mapping aarch64_vdso_maps[] __ro_after_init = {
},
[AA64_MAP_VDSO] = {
.name = "[vdso]",
- .mremap = vdso_mremap,
},
};

--
2.31.1