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