summaryrefslogtreecommitdiffstats
path: root/arch/arm/kernel/signal.c
diff options
context:
space:
mode:
authorJonathan Austin <jonathan.austin@arm.com>2013-04-18 19:37:24 +0200
committerJonathan Austin <jonathan.austin@arm.com>2013-06-17 16:13:18 +0200
commit9dfc28b6308096e48b54c28259825a1200f60742 (patch)
tree44e8b6cbe0935b20767bc79099780244d4c6722e /arch/arm/kernel/signal.c
parentARM: mpu: Allow enabling of the MPU via kconfig (diff)
downloadlinux-9dfc28b6308096e48b54c28259825a1200f60742.tar.xz
linux-9dfc28b6308096e48b54c28259825a1200f60742.zip
ARM: mpu: protect the vectors page with an MPU region
Without an MMU it is possible for userspace programs to start executing code in places that they have no business executing. The MPU allows some level of protection against this. This patch protects the vectors page from access by userspace processes. Userspace tasks that dereference a null pointer are already protected by an svc at 0x0 that kills them. However when tasks use an offset from a null pointer (eg a function in a null struct) they miss this carefully placed svc and enter the exception vectors in user mode, ending up in the kernel. This patch causes programs that do this to receive a SEGV instead of happily entering the kernel in user-mode, and hence avoid a 'Bad Mode' panic. As part of this change it is necessary to make sigreturn happen via the stack when there is not an sa_restorer function. This change is invisible to userspace, and irrelevant to code compiled using a uClibc toolchain, which always uses an sa_restorer function. Because we don't get to remap the vectors in !MMU kuser_helpers are not in a defined location, and hence aren't usable. This means we don't need to worry about keeping them accessible from PL0 Signed-off-by: Jonathan Austin <jonathan.austin@arm.com> Reviewed-by: Will Deacon <will.deacon@arm.com> CC: Nicolas Pitre <nico@linaro.org> CC: Catalin Marinas <catalin.marinas@arm.com>
Diffstat (limited to 'arch/arm/kernel/signal.c')
-rw-r--r--arch/arm/kernel/signal.c9
1 files changed, 7 insertions, 2 deletions
diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c
index 296786bdbb73..1c16c35c271a 100644
--- a/arch/arm/kernel/signal.c
+++ b/arch/arm/kernel/signal.c
@@ -392,14 +392,19 @@ setup_return(struct pt_regs *regs, struct ksignal *ksig,
if (ksig->ka.sa.sa_flags & SA_SIGINFO)
idx += 3;
+ /*
+ * Put the sigreturn code on the stack no matter which return
+ * mechanism we use in order to remain ABI compliant
+ */
if (__put_user(sigreturn_codes[idx], rc) ||
__put_user(sigreturn_codes[idx+1], rc+1))
return 1;
- if (cpsr & MODE32_BIT) {
+ if ((cpsr & MODE32_BIT) && !IS_ENABLED(CONFIG_ARM_MPU)) {
/*
* 32-bit code can use the new high-page
- * signal return code support.
+ * signal return code support except when the MPU has
+ * protected the vectors page from PL0
*/
retcode = KERN_SIGRETURN_CODE + (idx << 2) + thumb;
} else {