alistair23-linux/arch/arm/include/asm/mpu.h
Jonathan Austin 9dfc28b630 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>
2013-06-17 15:13:18 +01:00

77 lines
1.8 KiB
C

#ifndef __ARM_MPU_H
#define __ARM_MPU_H
#ifdef CONFIG_ARM_MPU
/* MPUIR layout */
#define MPUIR_nU 1
#define MPUIR_DREGION 8
#define MPUIR_IREGION 16
#define MPUIR_DREGION_SZMASK (0xFF << MPUIR_DREGION)
#define MPUIR_IREGION_SZMASK (0xFF << MPUIR_IREGION)
/* ID_MMFR0 data relevant to MPU */
#define MMFR0_PMSA (0xF << 4)
#define MMFR0_PMSAv7 (3 << 4)
/* MPU D/I Size Register fields */
#define MPU_RSR_SZ 1
#define MPU_RSR_EN 0
/* The D/I RSR value for an enabled region spanning the whole of memory */
#define MPU_RSR_ALL_MEM 63
/* Individual bits in the DR/IR ACR */
#define MPU_ACR_XN (1 << 12)
#define MPU_ACR_SHARED (1 << 2)
/* C, B and TEX[2:0] bits only have semantic meanings when grouped */
#define MPU_RGN_CACHEABLE 0xB
#define MPU_RGN_SHARED_CACHEABLE (MPU_RGN_CACHEABLE | MPU_ACR_SHARED)
#define MPU_RGN_STRONGLY_ORDERED 0
/* Main region should only be shared for SMP */
#ifdef CONFIG_SMP
#define MPU_RGN_NORMAL (MPU_RGN_CACHEABLE | MPU_ACR_SHARED)
#else
#define MPU_RGN_NORMAL MPU_RGN_CACHEABLE
#endif
/* Access permission bits of ACR (only define those that we use)*/
#define MPU_AP_PL1RW_PL0RW (0x3 << 8)
#define MPU_AP_PL1RW_PL0R0 (0x2 << 8)
#define MPU_AP_PL1RW_PL0NA (0x1 << 8)
/* For minimal static MPU region configurations */
#define MPU_PROBE_REGION 0
#define MPU_BG_REGION 1
#define MPU_RAM_REGION 2
#define MPU_VECTORS_REGION 3
/* Maximum number of regions Linux is interested in */
#define MPU_MAX_REGIONS 16
#define MPU_DATA_SIDE 0
#define MPU_INSTR_SIDE 1
#ifndef __ASSEMBLY__
struct mpu_rgn {
/* Assume same attributes for d/i-side */
u32 drbar;
u32 drsr;
u32 dracr;
};
struct mpu_rgn_info {
u32 mpuir;
struct mpu_rgn rgns[MPU_MAX_REGIONS];
};
extern struct mpu_rgn_info mpu_rgn_info;
#endif /* __ASSEMBLY__ */
#endif /* CONFIG_ARM_MPU */
#endif