From 6dc9f27c09cf380f70505c08bcd805e4495ab4f8 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Thu, 21 Apr 2016 18:04:53 +0100 Subject: MIPS: Prevent "restoration" of MSA context in non-MSA kernels commit 6533af4d4831c421cd9aa4dce7cfc19a3514cc09 upstream. If a kernel doesn't support MSA context (ie. CONFIG_CPU_HAS_MSA=n) then it will only keep 64 bits per FP register in thread context, and the calls to set_fpr64 in restore_msa_extcontext will overrun the end of the FP register context into the FCSR & MSACSR values. GCC 6.x has become smart enough to detect this & complain like so: arch/mips/kernel/signal.c: In function 'protected_restore_fp_context': ./arch/mips/include/asm/processor.h:114:17: error: array subscript is above array bounds [-Werror=array-bounds] fpr->val##width[FPR_IDX(width, idx)] = val; \ ~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~ ./arch/mips/include/asm/processor.h:118:1: note: in expansion of macro 'BUILD_FPR_ACCESS' BUILD_FPR_ACCESS(64) The only way to trigger this code to run would be for a program to set up an artificial extended MSA context structure following a sigframe & execute sigreturn. Whilst this doesn't allow a program to write to any state that it couldn't already, it makes little sense to allow this "restoration" of MSA context in a system that doesn't support MSA. Fix this by killing a program with SIGSYS if it tries something as crazy as "restoring" fake MSA context in this way, also fixing the build error & allowing for most of restore_msa_extcontext to be optimised out of kernels without support for MSA. Signed-off-by: Paul Burton Reported-by: Michal Toman Fixes: bf82cb30c7e5 ("MIPS: Save MSA extended context around signals") Tested-by: Aaro Koskinen Cc: James Hogan Cc: Michal Toman Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/13164/ Signed-off-by: Ralf Baechle Signed-off-by: Greg Kroah-Hartman --- arch/mips/kernel/signal.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'arch/mips/kernel/signal.c') diff --git a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c index bf792e2839a6..fc7c1f0b3d8d 100644 --- a/arch/mips/kernel/signal.c +++ b/arch/mips/kernel/signal.c @@ -195,6 +195,9 @@ static int restore_msa_extcontext(void __user *buf, unsigned int size) unsigned int csr; int i, err; + if (!config_enabled(CONFIG_CPU_HAS_MSA)) + return SIGSYS; + if (size != sizeof(*msa)) return -EINVAL; @@ -398,8 +401,8 @@ int protected_restore_fp_context(void __user *sc) } fp_done: - if (used & USED_EXTCONTEXT) - err |= restore_extcontext(sc_to_extcontext(sc)); + if (!err && (used & USED_EXTCONTEXT)) + err = restore_extcontext(sc_to_extcontext(sc)); return err ?: sig; } -- cgit v1.2.3 From 1985bf8d711a562dd143be05f05707333fbf7c7b Mon Sep 17 00:00:00 2001 From: James Hogan Date: Tue, 24 May 2016 09:35:10 +0100 Subject: MIPS: Fix sigreturn via VDSO on microMIPS kernel commit 13eb192d10bcc9ac518d57356179071d603bcb4e upstream. In microMIPS kernels, handle_signal() sets the isa16 mode bit in the vdso address so that the sigreturn trampolines (which are offset from the VDSO) get executed as microMIPS. However commit ebb5e78cc634 ("MIPS: Initial implementation of a VDSO") changed the offsets to come from the VDSO image, which already have the isa16 mode bit set correctly since they're extracted from the VDSO shared library symbol table. Drop the isa16 mode bit handling from handle_signal() to fix sigreturn for cores which support both microMIPS and normal MIPS. This doesn't fix microMIPS only cores, since the VDSO is still built for normal MIPS, but thats a separate problem. Fixes: ebb5e78cc634 ("MIPS: Initial implementation of a VDSO") Signed-off-by: James Hogan Cc: Paul Burton Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/13348/ Signed-off-by: Ralf Baechle Signed-off-by: Greg Kroah-Hartman --- arch/mips/kernel/signal.c | 8 -------- 1 file changed, 8 deletions(-) (limited to 'arch/mips/kernel/signal.c') diff --git a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c index fc7c1f0b3d8d..9e35b6b26aa8 100644 --- a/arch/mips/kernel/signal.c +++ b/arch/mips/kernel/signal.c @@ -770,15 +770,7 @@ static void handle_signal(struct ksignal *ksig, struct pt_regs *regs) sigset_t *oldset = sigmask_to_save(); int ret; struct mips_abi *abi = current->thread.abi; -#ifdef CONFIG_CPU_MICROMIPS - void *vdso; - unsigned long tmp = (unsigned long)current->mm->context.vdso; - - set_isa16_mode(tmp); - vdso = (void *)tmp; -#else void *vdso = current->mm->context.vdso; -#endif if (regs->regs[0]) { switch(regs->regs[2]) { -- cgit v1.2.3