aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm
diff options
context:
space:
mode:
authorRussell King <rmk+kernel@arm.linux.org.uk>2010-06-30 06:00:01 -0400
committerRussell King <rmk+kernel@arm.linux.org.uk>2010-06-30 06:00:01 -0400
commitfc4978b796e5e52ab3a709495a968199afe0a108 (patch)
tree102c74707940214f3c9810dadaf62d0d378a7a8c /arch/arm
parent3260e5293727f16ffdce9a6a6203fd9a6b149e58 (diff)
parentdf0698be14c6683606d5df2d83e3ae40f85ed0d9 (diff)
Merge git://git.linaro.org/nico/arm_security into devel-stable
Diffstat (limited to 'arch/arm')
-rw-r--r--arch/arm/Kconfig12
-rw-r--r--arch/arm/Makefile4
-rw-r--r--arch/arm/include/asm/elf.h3
-rw-r--r--arch/arm/include/asm/stackprotector.h38
-rw-r--r--arch/arm/kernel/asm-offsets.c3
-rw-r--r--arch/arm/kernel/entry-armv.S8
-rw-r--r--arch/arm/kernel/process.c13
-rw-r--r--arch/arm/mm/mmap.c4
8 files changed, 85 insertions, 0 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index c171f35b73a..2244de273d2 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1375,6 +1375,18 @@ config UACCESS_WITH_MEMCPY
1375 However, if the CPU data cache is using a write-allocate mode, 1375 However, if the CPU data cache is using a write-allocate mode,
1376 this option is unlikely to provide any performance gain. 1376 this option is unlikely to provide any performance gain.
1377 1377
1378config CC_STACKPROTECTOR
1379 bool "Enable -fstack-protector buffer overflow detection (EXPERIMENTAL)"
1380 help
1381 This option turns on the -fstack-protector GCC feature. This
1382 feature puts, at the beginning of functions, a canary value on
1383 the stack just before the return address, and validates
1384 the value just before actually returning. Stack based buffer
1385 overflows (that need to overwrite this return address) now also
1386 overwrite the canary, which gets detected and the attack is then
1387 neutralized via a kernel panic.
1388 This feature requires gcc version 4.2 or above.
1389
1378endmenu 1390endmenu
1379 1391
1380menu "Boot options" 1392menu "Boot options"
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 64ba313724d..ddf6da158ad 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -34,6 +34,10 @@ ifeq ($(CONFIG_FRAME_POINTER),y)
34KBUILD_CFLAGS +=-fno-omit-frame-pointer -mapcs -mno-sched-prolog 34KBUILD_CFLAGS +=-fno-omit-frame-pointer -mapcs -mno-sched-prolog
35endif 35endif
36 36
37ifeq ($(CONFIG_CC_STACKPROTECTOR),y)
38KBUILD_CFLAGS +=-fstack-protector
39endif
40
37ifeq ($(CONFIG_CPU_BIG_ENDIAN),y) 41ifeq ($(CONFIG_CPU_BIG_ENDIAN),y)
38KBUILD_CPPFLAGS += -mbig-endian 42KBUILD_CPPFLAGS += -mbig-endian
39AS += -EB 43AS += -EB
diff --git a/arch/arm/include/asm/elf.h b/arch/arm/include/asm/elf.h
index 51662feb9f1..0a96e8c1b82 100644
--- a/arch/arm/include/asm/elf.h
+++ b/arch/arm/include/asm/elf.h
@@ -121,4 +121,7 @@ int dump_task_regs(struct task_struct *t, elf_gregset_t *elfregs);
121extern void elf_set_personality(const struct elf32_hdr *); 121extern void elf_set_personality(const struct elf32_hdr *);
122#define SET_PERSONALITY(ex) elf_set_personality(&(ex)) 122#define SET_PERSONALITY(ex) elf_set_personality(&(ex))
123 123
124extern unsigned long arch_randomize_brk(struct mm_struct *mm);
125#define arch_randomize_brk arch_randomize_brk
126
124#endif 127#endif
diff --git a/arch/arm/include/asm/stackprotector.h b/arch/arm/include/asm/stackprotector.h
new file mode 100644
index 00000000000..de003327be9
--- /dev/null
+++ b/arch/arm/include/asm/stackprotector.h
@@ -0,0 +1,38 @@
1/*
2 * GCC stack protector support.
3 *
4 * Stack protector works by putting predefined pattern at the start of
5 * the stack frame and verifying that it hasn't been overwritten when
6 * returning from the function. The pattern is called stack canary
7 * and gcc expects it to be defined by a global variable called
8 * "__stack_chk_guard" on ARM. This unfortunately means that on SMP
9 * we cannot have a different canary value per task.
10 */
11
12#ifndef _ASM_STACKPROTECTOR_H
13#define _ASM_STACKPROTECTOR_H 1
14
15#include <linux/random.h>
16#include <linux/version.h>
17
18extern unsigned long __stack_chk_guard;
19
20/*
21 * Initialize the stackprotector canary value.
22 *
23 * NOTE: this must only be called from functions that never return,
24 * and it must always be inlined.
25 */
26static __always_inline void boot_init_stack_canary(void)
27{
28 unsigned long canary;
29
30 /* Try to get a semi random initial value. */
31 get_random_bytes(&canary, sizeof(canary));
32 canary ^= LINUX_VERSION_CODE;
33
34 current->stack_canary = canary;
35 __stack_chk_guard = current->stack_canary;
36}
37
38#endif /* _ASM_STACKPROTECTOR_H */
diff --git a/arch/arm/kernel/asm-offsets.c b/arch/arm/kernel/asm-offsets.c
index 883511522fc..85f2a019f77 100644
--- a/arch/arm/kernel/asm-offsets.c
+++ b/arch/arm/kernel/asm-offsets.c
@@ -40,6 +40,9 @@
40int main(void) 40int main(void)
41{ 41{
42 DEFINE(TSK_ACTIVE_MM, offsetof(struct task_struct, active_mm)); 42 DEFINE(TSK_ACTIVE_MM, offsetof(struct task_struct, active_mm));
43#ifdef CONFIG_CC_STACKPROTECTOR
44 DEFINE(TSK_STACK_CANARY, offsetof(struct task_struct, stack_canary));
45#endif
43 BLANK(); 46 BLANK();
44 DEFINE(TI_FLAGS, offsetof(struct thread_info, flags)); 47 DEFINE(TI_FLAGS, offsetof(struct thread_info, flags));
45 DEFINE(TI_PREEMPT, offsetof(struct thread_info, preempt_count)); 48 DEFINE(TI_PREEMPT, offsetof(struct thread_info, preempt_count));
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index 7ee48e7f8f3..2d14081b26b 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -745,6 +745,11 @@ ENTRY(__switch_to)
745 mov r4, #0xffff0fff 745 mov r4, #0xffff0fff
746 str r3, [r4, #-15] @ TLS val at 0xffff0ff0 746 str r3, [r4, #-15] @ TLS val at 0xffff0ff0
747#endif 747#endif
748#if defined(CONFIG_CC_STACKPROTECTOR) && !defined(CONFIG_SMP)
749 ldr r7, [r2, #TI_TASK]
750 ldr r8, =__stack_chk_guard
751 ldr r7, [r7, #TSK_STACK_CANARY]
752#endif
748#ifdef CONFIG_MMU 753#ifdef CONFIG_MMU
749 mcr p15, 0, r6, c3, c0, 0 @ Set domain register 754 mcr p15, 0, r6, c3, c0, 0 @ Set domain register
750#endif 755#endif
@@ -753,6 +758,9 @@ ENTRY(__switch_to)
753 ldr r0, =thread_notify_head 758 ldr r0, =thread_notify_head
754 mov r1, #THREAD_NOTIFY_SWITCH 759 mov r1, #THREAD_NOTIFY_SWITCH
755 bl atomic_notifier_call_chain 760 bl atomic_notifier_call_chain
761#if defined(CONFIG_CC_STACKPROTECTOR) && !defined(CONFIG_SMP)
762 str r7, [r8]
763#endif
756 THUMB( mov ip, r4 ) 764 THUMB( mov ip, r4 )
757 mov r0, r5 765 mov r0, r5
758 ARM( ldmia r4, {r4 - sl, fp, sp, pc} ) @ Load all regs saved previously 766 ARM( ldmia r4, {r4 - sl, fp, sp, pc} ) @ Load all regs saved previously
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c
index acf5e6fdb6d..090ac9459da 100644
--- a/arch/arm/kernel/process.c
+++ b/arch/arm/kernel/process.c
@@ -28,6 +28,7 @@
28#include <linux/tick.h> 28#include <linux/tick.h>
29#include <linux/utsname.h> 29#include <linux/utsname.h>
30#include <linux/uaccess.h> 30#include <linux/uaccess.h>
31#include <linux/random.h>
31 32
32#include <asm/leds.h> 33#include <asm/leds.h>
33#include <asm/processor.h> 34#include <asm/processor.h>
@@ -36,6 +37,12 @@
36#include <asm/stacktrace.h> 37#include <asm/stacktrace.h>
37#include <asm/mach/time.h> 38#include <asm/mach/time.h>
38 39
40#ifdef CONFIG_CC_STACKPROTECTOR
41#include <linux/stackprotector.h>
42unsigned long __stack_chk_guard __read_mostly;
43EXPORT_SYMBOL(__stack_chk_guard);
44#endif
45
39static const char *processor_modes[] = { 46static const char *processor_modes[] = {
40 "USER_26", "FIQ_26" , "IRQ_26" , "SVC_26" , "UK4_26" , "UK5_26" , "UK6_26" , "UK7_26" , 47 "USER_26", "FIQ_26" , "IRQ_26" , "SVC_26" , "UK4_26" , "UK5_26" , "UK6_26" , "UK7_26" ,
41 "UK8_26" , "UK9_26" , "UK10_26", "UK11_26", "UK12_26", "UK13_26", "UK14_26", "UK15_26", 48 "UK8_26" , "UK9_26" , "UK10_26", "UK11_26", "UK12_26", "UK13_26", "UK14_26", "UK15_26",
@@ -421,3 +428,9 @@ unsigned long get_wchan(struct task_struct *p)
421 } while (count ++ < 16); 428 } while (count ++ < 16);
422 return 0; 429 return 0;
423} 430}
431
432unsigned long arch_randomize_brk(struct mm_struct *mm)
433{
434 unsigned long range_end = mm->brk + 0x02000000;
435 return randomize_range(mm->brk, range_end, 0) ? : mm->brk;
436}
diff --git a/arch/arm/mm/mmap.c b/arch/arm/mm/mmap.c
index f5abc51c5a0..4f5b39687df 100644
--- a/arch/arm/mm/mmap.c
+++ b/arch/arm/mm/mmap.c
@@ -7,6 +7,7 @@
7#include <linux/shm.h> 7#include <linux/shm.h>
8#include <linux/sched.h> 8#include <linux/sched.h>
9#include <linux/io.h> 9#include <linux/io.h>
10#include <linux/random.h>
10#include <asm/cputype.h> 11#include <asm/cputype.h>
11#include <asm/system.h> 12#include <asm/system.h>
12 13
@@ -80,6 +81,9 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr,
80 start_addr = addr = TASK_UNMAPPED_BASE; 81 start_addr = addr = TASK_UNMAPPED_BASE;
81 mm->cached_hole_size = 0; 82 mm->cached_hole_size = 0;
82 } 83 }
84 /* 8 bits of randomness in 20 address space bits */
85 if (current->flags & PF_RANDOMIZE)
86 addr += (get_random_int() % (1 << 8)) << PAGE_SHIFT;
83 87
84full_search: 88full_search:
85 if (do_align) 89 if (do_align)