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

Signed-off-by: Dmitry Safonov <d...@arista.com>
---
 arch/arm64/kernel/signal.c | 10 +++++++---
 arch/arm64/kernel/vdso.c   | 13 +++----------
 2 files changed, 10 insertions(+), 13 deletions(-)

diff --git a/arch/arm64/kernel/signal.c b/arch/arm64/kernel/signal.c
index bec6ef69704f..4c1dfbc1aed3 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->user_landing;
        __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_USER_LANDING)
+               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 08e8f1d56d92..d710fcd7141c 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 __vdso_init(enum vdso_abi abi)
 {
        int i;
@@ -239,7 +233,6 @@ static int __setup_additional_pages(enum vdso_abi abi,
                gp_flags = VM_ARM64_BTI;
 
        vdso_base += VVAR_NR_PAGES * PAGE_SIZE;
-       mm->context.vdso = (void *)vdso_base;
        ret = _install_special_mapping(mm, vdso_base, vdso_text_len,
                                       VM_READ|VM_EXEC|gp_flags|
                                       VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC,
@@ -247,12 +240,14 @@ static int __setup_additional_pages(enum vdso_abi abi,
        if (IS_ERR(ret))
                goto up_fail;
 
+       /* 32-bit ABI is to land on sigpage, 64-bit on vdso */
+       if (abi == VDSO_ABI_AA64)
+               mm->user_landing = (void __user *)vdso_base;
        *sysinfo_ehdr = vdso_base;
 
        return 0;
 
 up_fail:
-       mm->context.vdso = NULL;
        return PTR_ERR(ret);
 }
 
@@ -285,7 +280,6 @@ static struct vm_special_mapping aarch32_vdso_maps[] = {
        },
        [AA32_MAP_VDSO] = {
                .name = "[vdso]",
-               .mremap = vdso_mremap,
        },
 };
 
@@ -431,7 +425,6 @@ static struct vm_special_mapping aarch64_vdso_maps[] 
__ro_after_init = {
        },
        [AA64_MAP_VDSO] = {
                .name   = "[vdso]",
-               .mremap = vdso_mremap,
        },
 };
 
-- 
2.28.0

Reply via email to