Generic way to track the land vma area. As a bonus, after unmapping sigpage, kernel won't try to land on its previous position. Cc: Thomas Bogendoerfer <tsbogend@xxxxxxxxxxxxxxxx> Cc: linux-mips@xxxxxxxxxxxxxxx Signed-off-by: Dmitry Safonov <dima@xxxxxxxxxx> --- arch/mips/Kconfig | 1 + arch/mips/kernel/signal.c | 11 +++++++---- arch/mips/kernel/vdso.c | 2 +- arch/mips/vdso/genvdso.c | 8 -------- 4 files changed, 9 insertions(+), 13 deletions(-) diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 5e696ab80df4..eedb1683ec8e 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -10,6 +10,7 @@ config MIPS select ARCH_HAS_SETUP_ADDITIONAL_PAGES select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST select ARCH_HAS_UBSAN_SANITIZE_ALL + select ARCH_HAS_USER_LANDING select ARCH_SUPPORTS_UPROBES select ARCH_USE_BUILTIN_BSWAP select ARCH_USE_CMPXCHG_LOCKREF if 64BIT diff --git a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c index f1e985109da0..eb79272d3cc2 100644 --- a/arch/mips/kernel/signal.c +++ b/arch/mips/kernel/signal.c @@ -806,11 +806,13 @@ struct mips_abi mips_abi = { static void handle_signal(struct ksignal *ksig, struct pt_regs *regs) { + unsigned long land = (unsigned long)current->mm->user_landing; sigset_t *oldset = sigmask_to_save(); - int ret; + int ret = 1; struct mips_abi *abi = current->thread.abi; - void *vdso = current->mm->context.vdso; + if (land == UNMAPPED_USER_LANDING) + goto err; /* * If we were emulating a delay slot instruction, exit that frame such * that addresses in the sigframe are as expected for userland and we @@ -843,12 +845,13 @@ static void handle_signal(struct ksignal *ksig, struct pt_regs *regs) rseq_signal_deliver(ksig, regs); if (sig_uses_siginfo(&ksig->ka, abi)) - ret = abi->setup_rt_frame(vdso + abi->vdso->off_rt_sigreturn, + ret = abi->setup_rt_frame(land + abi->vdso->off_rt_sigreturn, ksig, regs, oldset); else - ret = abi->setup_frame(vdso + abi->vdso->off_sigreturn, + ret = abi->setup_frame(land + abi->vdso->off_sigreturn, ksig, regs, oldset); +err: signal_setup_done(ret, ksig, 0); } diff --git a/arch/mips/kernel/vdso.c b/arch/mips/kernel/vdso.c index a4a321252df6..5523ba25ab3d 100644 --- a/arch/mips/kernel/vdso.c +++ b/arch/mips/kernel/vdso.c @@ -183,7 +183,7 @@ int arch_setup_additional_pages(unsigned long *sysinfo_ehdr) goto out; } - mm->context.vdso = (void *)vdso_addr; + mm->user_landing = (void __user *)vdso_addr; *sysinfo_ehdr = vdso_addr; ret = 0; diff --git a/arch/mips/vdso/genvdso.c b/arch/mips/vdso/genvdso.c index 0303d30cde03..8f581a2c8578 100644 --- a/arch/mips/vdso/genvdso.c +++ b/arch/mips/vdso/genvdso.c @@ -259,13 +259,6 @@ int main(int argc, char **argv) fprintf(out_file, "#include <linux/linkage.h>\n"); fprintf(out_file, "#include <linux/mm.h>\n"); fprintf(out_file, "#include <asm/vdso.h>\n"); - fprintf(out_file, "static void vdso_mremap(\n"); - fprintf(out_file, " const struct vm_special_mapping *sm,\n"); - fprintf(out_file, " struct vm_area_struct *new_vma)\n"); - fprintf(out_file, "{\n"); - fprintf(out_file, " current->mm->context.vdso =\n"); - fprintf(out_file, " (void *)(new_vma->vm_start);\n"); - fprintf(out_file, "}\n"); /* Write out the stripped VDSO data. */ fprintf(out_file, @@ -290,7 +283,6 @@ int main(int argc, char **argv) fprintf(out_file, "\t.mapping = {\n"); fprintf(out_file, "\t\t.name = \"[vdso]\",\n"); fprintf(out_file, "\t\t.pages = vdso_pages,\n"); - fprintf(out_file, "\t\t.mremap = vdso_mremap,\n"); fprintf(out_file, "\t},\n"); /* Calculate and write symbol offsets to <output file> */ -- 2.28.0