diff options
author | Kees Cook <keescook@chromium.org> | 2014-04-03 16:29:50 -0400 |
---|---|---|
committer | Kees Cook <keescook@chromium.org> | 2014-10-16 17:38:54 -0400 |
commit | 80d6b0c2eed2a504f6740cd1f5ea76dc50abfc4d (patch) | |
tree | 32f6d8a1c5a2250cc3f303df545dfbf52da62d19 /arch/arm/kernel | |
parent | 1e6b48116a95046ec51f3d40f83aff8b006674d7 (diff) |
ARM: mm: allow text and rodata sections to be read-only
This introduces CONFIG_DEBUG_RODATA, making kernel text and rodata
read-only. Additionally, this splits rodata from text so that rodata can
also be NX, which may lead to wasted memory when aligning to SECTION_SIZE.
The read-only areas are made writable during ftrace updates and kexec.
Signed-off-by: Kees Cook <keescook@chromium.org>
Tested-by: Laura Abbott <lauraa@codeaurora.org>
Acked-by: Nicolas Pitre <nico@linaro.org>
Diffstat (limited to 'arch/arm/kernel')
-rw-r--r-- | arch/arm/kernel/ftrace.c | 19 | ||||
-rw-r--r-- | arch/arm/kernel/machine_kexec.c | 1 | ||||
-rw-r--r-- | arch/arm/kernel/vmlinux.lds.S | 3 |
3 files changed, 23 insertions, 0 deletions
diff --git a/arch/arm/kernel/ftrace.c b/arch/arm/kernel/ftrace.c index af9a8a927a4e..b8c75e45a950 100644 --- a/arch/arm/kernel/ftrace.c +++ b/arch/arm/kernel/ftrace.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/ftrace.h> | 15 | #include <linux/ftrace.h> |
16 | #include <linux/uaccess.h> | 16 | #include <linux/uaccess.h> |
17 | #include <linux/module.h> | 17 | #include <linux/module.h> |
18 | #include <linux/stop_machine.h> | ||
18 | 19 | ||
19 | #include <asm/cacheflush.h> | 20 | #include <asm/cacheflush.h> |
20 | #include <asm/opcodes.h> | 21 | #include <asm/opcodes.h> |
@@ -35,6 +36,22 @@ | |||
35 | 36 | ||
36 | #define OLD_NOP 0xe1a00000 /* mov r0, r0 */ | 37 | #define OLD_NOP 0xe1a00000 /* mov r0, r0 */ |
37 | 38 | ||
39 | static int __ftrace_modify_code(void *data) | ||
40 | { | ||
41 | int *command = data; | ||
42 | |||
43 | set_kernel_text_rw(); | ||
44 | ftrace_modify_all_code(*command); | ||
45 | set_kernel_text_ro(); | ||
46 | |||
47 | return 0; | ||
48 | } | ||
49 | |||
50 | void arch_ftrace_update_code(int command) | ||
51 | { | ||
52 | stop_machine(__ftrace_modify_code, &command, NULL); | ||
53 | } | ||
54 | |||
38 | static unsigned long ftrace_nop_replace(struct dyn_ftrace *rec) | 55 | static unsigned long ftrace_nop_replace(struct dyn_ftrace *rec) |
39 | { | 56 | { |
40 | return rec->arch.old_mcount ? OLD_NOP : NOP; | 57 | return rec->arch.old_mcount ? OLD_NOP : NOP; |
@@ -73,6 +90,8 @@ int ftrace_arch_code_modify_prepare(void) | |||
73 | int ftrace_arch_code_modify_post_process(void) | 90 | int ftrace_arch_code_modify_post_process(void) |
74 | { | 91 | { |
75 | set_all_modules_text_ro(); | 92 | set_all_modules_text_ro(); |
93 | /* Make sure any TLB misses during machine stop are cleared. */ | ||
94 | flush_tlb_all(); | ||
76 | return 0; | 95 | return 0; |
77 | } | 96 | } |
78 | 97 | ||
diff --git a/arch/arm/kernel/machine_kexec.c b/arch/arm/kernel/machine_kexec.c index 8f75250cbe30..4423a565ef6f 100644 --- a/arch/arm/kernel/machine_kexec.c +++ b/arch/arm/kernel/machine_kexec.c | |||
@@ -164,6 +164,7 @@ void machine_kexec(struct kimage *image) | |||
164 | reboot_code_buffer = page_address(image->control_code_page); | 164 | reboot_code_buffer = page_address(image->control_code_page); |
165 | 165 | ||
166 | /* Prepare parameters for reboot_code_buffer*/ | 166 | /* Prepare parameters for reboot_code_buffer*/ |
167 | set_kernel_text_rw(); | ||
167 | kexec_start_address = image->start; | 168 | kexec_start_address = image->start; |
168 | kexec_indirection_page = page_list; | 169 | kexec_indirection_page = page_list; |
169 | kexec_mach_type = machine_arch_type; | 170 | kexec_mach_type = machine_arch_type; |
diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S index 18fd68a295ea..3afcb6c2cf06 100644 --- a/arch/arm/kernel/vmlinux.lds.S +++ b/arch/arm/kernel/vmlinux.lds.S | |||
@@ -120,6 +120,9 @@ SECTIONS | |||
120 | ARM_CPU_KEEP(PROC_INFO) | 120 | ARM_CPU_KEEP(PROC_INFO) |
121 | } | 121 | } |
122 | 122 | ||
123 | #ifdef CONFIG_DEBUG_RODATA | ||
124 | . = ALIGN(1<<SECTION_SHIFT); | ||
125 | #endif | ||
123 | RO_DATA(PAGE_SIZE) | 126 | RO_DATA(PAGE_SIZE) |
124 | 127 | ||
125 | . = ALIGN(4); | 128 | . = ALIGN(4); |