diff options
Diffstat (limited to 'arch/x86')
-rw-r--r-- | arch/x86/include/asm/cacheflush.h | 5 | ||||
-rw-r--r-- | arch/x86/kernel/ftrace.c | 13 | ||||
-rw-r--r-- | arch/x86/mm/init_32.c | 35 | ||||
-rw-r--r-- | arch/x86/mm/init_64.c | 37 |
4 files changed, 82 insertions, 8 deletions
diff --git a/arch/x86/include/asm/cacheflush.h b/arch/x86/include/asm/cacheflush.h index 2f8466540fb5..6145063cfe0e 100644 --- a/arch/x86/include/asm/cacheflush.h +++ b/arch/x86/include/asm/cacheflush.h | |||
@@ -104,6 +104,11 @@ void clflush_cache_range(void *addr, unsigned int size); | |||
104 | #ifdef CONFIG_DEBUG_RODATA | 104 | #ifdef CONFIG_DEBUG_RODATA |
105 | void mark_rodata_ro(void); | 105 | void mark_rodata_ro(void); |
106 | extern const int rodata_test_data; | 106 | extern const int rodata_test_data; |
107 | void set_kernel_text_rw(void); | ||
108 | void set_kernel_text_ro(void); | ||
109 | #else | ||
110 | static inline void set_kernel_text_rw(void) { } | ||
111 | static inline void set_kernel_text_ro(void) { } | ||
107 | #endif | 112 | #endif |
108 | 113 | ||
109 | #ifdef CONFIG_DEBUG_RODATA_TEST | 114 | #ifdef CONFIG_DEBUG_RODATA_TEST |
diff --git a/arch/x86/kernel/ftrace.c b/arch/x86/kernel/ftrace.c index 231bdd3c5b1c..77857d4f7d0f 100644 --- a/arch/x86/kernel/ftrace.c +++ b/arch/x86/kernel/ftrace.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/init.h> | 18 | #include <linux/init.h> |
19 | #include <linux/list.h> | 19 | #include <linux/list.h> |
20 | 20 | ||
21 | #include <asm/cacheflush.h> | ||
21 | #include <asm/ftrace.h> | 22 | #include <asm/ftrace.h> |
22 | #include <linux/ftrace.h> | 23 | #include <linux/ftrace.h> |
23 | #include <asm/nops.h> | 24 | #include <asm/nops.h> |
@@ -26,6 +27,18 @@ | |||
26 | 27 | ||
27 | #ifdef CONFIG_DYNAMIC_FTRACE | 28 | #ifdef CONFIG_DYNAMIC_FTRACE |
28 | 29 | ||
30 | int ftrace_arch_code_modify_prepare(void) | ||
31 | { | ||
32 | set_kernel_text_rw(); | ||
33 | return 0; | ||
34 | } | ||
35 | |||
36 | int ftrace_arch_code_modify_post_process(void) | ||
37 | { | ||
38 | set_kernel_text_ro(); | ||
39 | return 0; | ||
40 | } | ||
41 | |||
29 | union ftrace_code_union { | 42 | union ftrace_code_union { |
30 | char code[MCOUNT_INSN_SIZE]; | 43 | char code[MCOUNT_INSN_SIZE]; |
31 | struct { | 44 | struct { |
diff --git a/arch/x86/mm/init_32.c b/arch/x86/mm/init_32.c index 2cef05074413..3eb2ed188a4c 100644 --- a/arch/x86/mm/init_32.c +++ b/arch/x86/mm/init_32.c | |||
@@ -1155,17 +1155,47 @@ static noinline int do_test_wp_bit(void) | |||
1155 | const int rodata_test_data = 0xC3; | 1155 | const int rodata_test_data = 0xC3; |
1156 | EXPORT_SYMBOL_GPL(rodata_test_data); | 1156 | EXPORT_SYMBOL_GPL(rodata_test_data); |
1157 | 1157 | ||
1158 | static int kernel_set_to_readonly; | ||
1159 | |||
1160 | void set_kernel_text_rw(void) | ||
1161 | { | ||
1162 | unsigned long start = PFN_ALIGN(_text); | ||
1163 | unsigned long size = PFN_ALIGN(_etext) - start; | ||
1164 | |||
1165 | if (!kernel_set_to_readonly) | ||
1166 | return; | ||
1167 | |||
1168 | pr_debug("Set kernel text: %lx - %lx for read write\n", | ||
1169 | start, start+size); | ||
1170 | |||
1171 | set_pages_rw(virt_to_page(start), size >> PAGE_SHIFT); | ||
1172 | } | ||
1173 | |||
1174 | void set_kernel_text_ro(void) | ||
1175 | { | ||
1176 | unsigned long start = PFN_ALIGN(_text); | ||
1177 | unsigned long size = PFN_ALIGN(_etext) - start; | ||
1178 | |||
1179 | if (!kernel_set_to_readonly) | ||
1180 | return; | ||
1181 | |||
1182 | pr_debug("Set kernel text: %lx - %lx for read only\n", | ||
1183 | start, start+size); | ||
1184 | |||
1185 | set_pages_ro(virt_to_page(start), size >> PAGE_SHIFT); | ||
1186 | } | ||
1187 | |||
1158 | void mark_rodata_ro(void) | 1188 | void mark_rodata_ro(void) |
1159 | { | 1189 | { |
1160 | unsigned long start = PFN_ALIGN(_text); | 1190 | unsigned long start = PFN_ALIGN(_text); |
1161 | unsigned long size = PFN_ALIGN(_etext) - start; | 1191 | unsigned long size = PFN_ALIGN(_etext) - start; |
1162 | 1192 | ||
1163 | #ifndef CONFIG_DYNAMIC_FTRACE | ||
1164 | /* Dynamic tracing modifies the kernel text section */ | ||
1165 | set_pages_ro(virt_to_page(start), size >> PAGE_SHIFT); | 1193 | set_pages_ro(virt_to_page(start), size >> PAGE_SHIFT); |
1166 | printk(KERN_INFO "Write protecting the kernel text: %luk\n", | 1194 | printk(KERN_INFO "Write protecting the kernel text: %luk\n", |
1167 | size >> 10); | 1195 | size >> 10); |
1168 | 1196 | ||
1197 | kernel_set_to_readonly = 1; | ||
1198 | |||
1169 | #ifdef CONFIG_CPA_DEBUG | 1199 | #ifdef CONFIG_CPA_DEBUG |
1170 | printk(KERN_INFO "Testing CPA: Reverting %lx-%lx\n", | 1200 | printk(KERN_INFO "Testing CPA: Reverting %lx-%lx\n", |
1171 | start, start+size); | 1201 | start, start+size); |
@@ -1174,7 +1204,6 @@ void mark_rodata_ro(void) | |||
1174 | printk(KERN_INFO "Testing CPA: write protecting again\n"); | 1204 | printk(KERN_INFO "Testing CPA: write protecting again\n"); |
1175 | set_pages_ro(virt_to_page(start), size>>PAGE_SHIFT); | 1205 | set_pages_ro(virt_to_page(start), size>>PAGE_SHIFT); |
1176 | #endif | 1206 | #endif |
1177 | #endif /* CONFIG_DYNAMIC_FTRACE */ | ||
1178 | 1207 | ||
1179 | start += size; | 1208 | start += size; |
1180 | size = (unsigned long)__end_rodata - start; | 1209 | size = (unsigned long)__end_rodata - start; |
diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c index e6d36b490250..63fdc531601d 100644 --- a/arch/x86/mm/init_64.c +++ b/arch/x86/mm/init_64.c | |||
@@ -986,21 +986,48 @@ void free_initmem(void) | |||
986 | const int rodata_test_data = 0xC3; | 986 | const int rodata_test_data = 0xC3; |
987 | EXPORT_SYMBOL_GPL(rodata_test_data); | 987 | EXPORT_SYMBOL_GPL(rodata_test_data); |
988 | 988 | ||
989 | static int kernel_set_to_readonly; | ||
990 | |||
991 | void set_kernel_text_rw(void) | ||
992 | { | ||
993 | unsigned long start = PFN_ALIGN(_stext); | ||
994 | unsigned long end = PFN_ALIGN(__start_rodata); | ||
995 | |||
996 | if (!kernel_set_to_readonly) | ||
997 | return; | ||
998 | |||
999 | pr_debug("Set kernel text: %lx - %lx for read write\n", | ||
1000 | start, end); | ||
1001 | |||
1002 | set_memory_rw(start, (end - start) >> PAGE_SHIFT); | ||
1003 | } | ||
1004 | |||
1005 | void set_kernel_text_ro(void) | ||
1006 | { | ||
1007 | unsigned long start = PFN_ALIGN(_stext); | ||
1008 | unsigned long end = PFN_ALIGN(__start_rodata); | ||
1009 | |||
1010 | if (!kernel_set_to_readonly) | ||
1011 | return; | ||
1012 | |||
1013 | pr_debug("Set kernel text: %lx - %lx for read only\n", | ||
1014 | start, end); | ||
1015 | |||
1016 | set_memory_ro(start, (end - start) >> PAGE_SHIFT); | ||
1017 | } | ||
1018 | |||
989 | void mark_rodata_ro(void) | 1019 | void mark_rodata_ro(void) |
990 | { | 1020 | { |
991 | unsigned long start = PFN_ALIGN(_stext), end = PFN_ALIGN(__end_rodata); | 1021 | unsigned long start = PFN_ALIGN(_stext), end = PFN_ALIGN(__end_rodata); |
992 | unsigned long rodata_start = | 1022 | unsigned long rodata_start = |
993 | ((unsigned long)__start_rodata + PAGE_SIZE - 1) & PAGE_MASK; | 1023 | ((unsigned long)__start_rodata + PAGE_SIZE - 1) & PAGE_MASK; |
994 | 1024 | ||
995 | #ifdef CONFIG_DYNAMIC_FTRACE | ||
996 | /* Dynamic tracing modifies the kernel text section */ | ||
997 | start = rodata_start; | ||
998 | #endif | ||
999 | |||
1000 | printk(KERN_INFO "Write protecting the kernel read-only data: %luk\n", | 1025 | printk(KERN_INFO "Write protecting the kernel read-only data: %luk\n", |
1001 | (end - start) >> 10); | 1026 | (end - start) >> 10); |
1002 | set_memory_ro(start, (end - start) >> PAGE_SHIFT); | 1027 | set_memory_ro(start, (end - start) >> PAGE_SHIFT); |
1003 | 1028 | ||
1029 | kernel_set_to_readonly = 1; | ||
1030 | |||
1004 | /* | 1031 | /* |
1005 | * The rodata section (but not the kernel text!) should also be | 1032 | * The rodata section (but not the kernel text!) should also be |
1006 | * not-executable. | 1033 | * not-executable. |