Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

x86/mm: Always enable CONFIG_DEBUG_RODATA and remove the Kconfig option

This removes the CONFIG_DEBUG_RODATA option and makes it always enabled.

This simplifies the code and also makes it clearer that read-only mapped
memory is just as fundamental a security feature in kernel-space as it is
in user-space.

Suggested-by: Ingo Molnar <mingo@kernel.org>
Signed-off-by: Kees Cook <keescook@chromium.org>
Cc: Andy Lutomirski <luto@amacapital.net>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: David Brown <david.brown@linaro.org>
Cc: Denys Vlasenko <dvlasenk@redhat.com>
Cc: Emese Revfy <re.emese@gmail.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Mathias Krause <minipli@googlemail.com>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: PaX Team <pageexec@freemail.hu>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: kernel-hardening@lists.openwall.com
Cc: linux-arch <linux-arch@vger.kernel.org>
Link: http://lkml.kernel.org/r/1455748879-21872-4-git-send-email-keescook@chromium.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>

authored by

Kees Cook and committed by
Ingo Molnar
9ccaf77c d2aa1aca

+25 -61
+3
arch/x86/Kconfig
··· 303 303 config FIX_EARLYCON_MEM 304 304 def_bool y 305 305 306 + config DEBUG_RODATA 307 + def_bool y 308 + 306 309 config PGTABLE_LEVELS 307 310 int 308 311 default 4 if X86_64
+3 -15
arch/x86/Kconfig.debug
··· 74 74 issues with the mapping of the EFI runtime regions into that 75 75 table. 76 76 77 - config DEBUG_RODATA 78 - bool "Write protect kernel read-only data structures" 79 - default y 80 - depends on DEBUG_KERNEL 81 - ---help--- 82 - Mark the kernel read-only data as write-protected in the pagetables, 83 - in order to catch accidental (and incorrect) writes to such const 84 - data. This is recommended so that we can catch kernel bugs sooner. 85 - If in doubt, say "Y". 86 - 87 77 config DEBUG_RODATA_TEST 88 - bool "Testcase for the DEBUG_RODATA feature" 89 - depends on DEBUG_RODATA 78 + bool "Testcase for the marking rodata read-only" 90 79 default y 91 80 ---help--- 92 - This option enables a testcase for the DEBUG_RODATA 93 - feature as well as for the change_page_attr() infrastructure. 81 + This option enables a testcase for the setting rodata read-only 82 + as well as for the change_page_attr() infrastructure. 94 83 If in doubt, say "N" 95 84 96 85 config DEBUG_WX 97 86 bool "Warn on W+X mappings at boot" 98 - depends on DEBUG_RODATA 99 87 select X86_PTDUMP_CORE 100 88 ---help--- 101 89 Generate a warning if any W+X mappings are found at boot.
-5
arch/x86/include/asm/cacheflush.h
··· 91 91 92 92 #define mmio_flush_range(addr, size) clflush_cache_range(addr, size) 93 93 94 - #ifdef CONFIG_DEBUG_RODATA 95 94 extern const int rodata_test_data; 96 95 extern int kernel_set_to_readonly; 97 96 void set_kernel_text_rw(void); 98 97 void set_kernel_text_ro(void); 99 - #else 100 - static inline void set_kernel_text_rw(void) { } 101 - static inline void set_kernel_text_ro(void) { } 102 - #endif 103 98 104 99 #ifdef CONFIG_DEBUG_RODATA_TEST 105 100 int rodata_test(void);
-7
arch/x86/include/asm/kvm_para.h
··· 17 17 } 18 18 #endif /* CONFIG_KVM_GUEST */ 19 19 20 - #ifdef CONFIG_DEBUG_RODATA 21 20 #define KVM_HYPERCALL \ 22 21 ALTERNATIVE(".byte 0x0f,0x01,0xc1", ".byte 0x0f,0x01,0xd9", X86_FEATURE_VMMCALL) 23 - #else 24 - /* On AMD processors, vmcall will generate a trap that we will 25 - * then rewrite to the appropriate instruction. 26 - */ 27 - #define KVM_HYPERCALL ".byte 0x0f,0x01,0xc1" 28 - #endif 29 22 30 23 /* For KVM hypercalls, a three-byte sequence of either the vmcall or the vmmcall 31 24 * instruction. The hypervisor may replace it with something else but only the
+1 -1
arch/x86/include/asm/sections.h
··· 7 7 extern char __brk_base[], __brk_limit[]; 8 8 extern struct exception_table_entry __stop___ex_table[]; 9 9 10 - #if defined(CONFIG_X86_64) && defined(CONFIG_DEBUG_RODATA) 10 + #if defined(CONFIG_X86_64) 11 11 extern char __end_rodata_hpage_align[]; 12 12 #endif 13 13
+3 -3
arch/x86/kernel/ftrace.c
··· 81 81 static unsigned long text_ip_addr(unsigned long ip) 82 82 { 83 83 /* 84 - * On x86_64, kernel text mappings are mapped read-only with 85 - * CONFIG_DEBUG_RODATA. So we use the kernel identity mapping instead 86 - * of the kernel text mapping to modify the kernel text. 84 + * On x86_64, kernel text mappings are mapped read-only, so we use 85 + * the kernel identity mapping instead of the kernel text mapping 86 + * to modify the kernel text. 87 87 * 88 88 * For 32bit kernels, these mappings are same and we can use 89 89 * kernel identity mapping to modify code.
+2 -6
arch/x86/kernel/kgdb.c
··· 750 750 int kgdb_arch_set_breakpoint(struct kgdb_bkpt *bpt) 751 751 { 752 752 int err; 753 - #ifdef CONFIG_DEBUG_RODATA 754 753 char opc[BREAK_INSTR_SIZE]; 755 - #endif /* CONFIG_DEBUG_RODATA */ 756 754 757 755 bpt->type = BP_BREAKPOINT; 758 756 err = probe_kernel_read(bpt->saved_instr, (char *)bpt->bpt_addr, ··· 759 761 return err; 760 762 err = probe_kernel_write((char *)bpt->bpt_addr, 761 763 arch_kgdb_ops.gdb_bpt_instr, BREAK_INSTR_SIZE); 762 - #ifdef CONFIG_DEBUG_RODATA 763 764 if (!err) 764 765 return err; 765 766 /* ··· 775 778 if (memcmp(opc, arch_kgdb_ops.gdb_bpt_instr, BREAK_INSTR_SIZE)) 776 779 return -EINVAL; 777 780 bpt->type = BP_POKE_BREAKPOINT; 778 - #endif /* CONFIG_DEBUG_RODATA */ 781 + 779 782 return err; 780 783 } 781 784 782 785 int kgdb_arch_remove_breakpoint(struct kgdb_bkpt *bpt) 783 786 { 784 - #ifdef CONFIG_DEBUG_RODATA 785 787 int err; 786 788 char opc[BREAK_INSTR_SIZE]; 787 789 ··· 797 801 if (err || memcmp(opc, bpt->saved_instr, BREAK_INSTR_SIZE)) 798 802 goto knl_write; 799 803 return err; 804 + 800 805 knl_write: 801 - #endif /* CONFIG_DEBUG_RODATA */ 802 806 return probe_kernel_write((char *)bpt->bpt_addr, 803 807 (char *)bpt->saved_instr, BREAK_INSTR_SIZE); 804 808 }
-2
arch/x86/kernel/test_nx.c
··· 142 142 * by the error message 143 143 */ 144 144 145 - #ifdef CONFIG_DEBUG_RODATA 146 145 /* Test 3: Check if the .rodata section is executable */ 147 146 if (rodata_test_data != 0xC3) { 148 147 printk(KERN_ERR "test_nx: .rodata marker has invalid value\n"); ··· 150 151 printk(KERN_ERR "test_nx: .rodata section is executable\n"); 151 152 ret = -ENODEV; 152 153 } 153 - #endif 154 154 155 155 #if 0 156 156 /* Test 4: Check if the .data section of a module is executable */
+1 -1
arch/x86/kernel/test_rodata.c
··· 76 76 } 77 77 78 78 MODULE_LICENSE("GPL"); 79 - MODULE_DESCRIPTION("Testcase for the DEBUG_RODATA infrastructure"); 79 + MODULE_DESCRIPTION("Testcase for marking rodata as read-only"); 80 80 MODULE_AUTHOR("Arjan van de Ven <arjan@linux.intel.com>");
+11 -14
arch/x86/kernel/vmlinux.lds.S
··· 41 41 jiffies_64 = jiffies; 42 42 #endif 43 43 44 - #if defined(CONFIG_X86_64) && defined(CONFIG_DEBUG_RODATA) 44 + #if defined(CONFIG_X86_64) 45 45 /* 46 - * On 64-bit, align RODATA to 2MB so that even with CONFIG_DEBUG_RODATA 47 - * we retain large page mappings for boundaries spanning kernel text, rodata 48 - * and data sections. 46 + * On 64-bit, align RODATA to 2MB so we retain large page mappings for 47 + * boundaries spanning kernel text, rodata and data sections. 49 48 * 50 49 * However, kernel identity mappings will have different RWX permissions 51 50 * to the pages mapping to text and to the pages padding (which are freed) the 52 51 * text section. Hence kernel identity mappings will be broken to smaller 53 52 * pages. For 64-bit, kernel text and kernel identity mappings are different, 54 - * so we can enable protection checks that come with CONFIG_DEBUG_RODATA, 55 - * as well as retain 2MB large page mappings for kernel text. 53 + * so we can enable protection checks as well as retain 2MB large page 54 + * mappings for kernel text. 56 55 */ 57 - #define X64_ALIGN_DEBUG_RODATA_BEGIN . = ALIGN(HPAGE_SIZE); 56 + #define X64_ALIGN_RODATA_BEGIN . = ALIGN(HPAGE_SIZE); 58 57 59 - #define X64_ALIGN_DEBUG_RODATA_END \ 58 + #define X64_ALIGN_RODATA_END \ 60 59 . = ALIGN(HPAGE_SIZE); \ 61 60 __end_rodata_hpage_align = .; 62 61 63 62 #else 64 63 65 - #define X64_ALIGN_DEBUG_RODATA_BEGIN 66 - #define X64_ALIGN_DEBUG_RODATA_END 64 + #define X64_ALIGN_RODATA_BEGIN 65 + #define X64_ALIGN_RODATA_END 67 66 68 67 #endif 69 68 ··· 111 112 112 113 EXCEPTION_TABLE(16) :text = 0x9090 113 114 114 - #if defined(CONFIG_DEBUG_RODATA) 115 115 /* .text should occupy whole number of pages */ 116 116 . = ALIGN(PAGE_SIZE); 117 - #endif 118 - X64_ALIGN_DEBUG_RODATA_BEGIN 117 + X64_ALIGN_RODATA_BEGIN 119 118 RO_DATA(PAGE_SIZE) 120 - X64_ALIGN_DEBUG_RODATA_END 119 + X64_ALIGN_RODATA_END 121 120 122 121 /* Data */ 123 122 .data : AT(ADDR(.data) - LOAD_OFFSET) {
-3
arch/x86/mm/init_32.c
··· 871 871 return flag; 872 872 } 873 873 874 - #ifdef CONFIG_DEBUG_RODATA 875 874 const int rodata_test_data = 0xC3; 876 875 EXPORT_SYMBOL_GPL(rodata_test_data); 877 876 ··· 959 960 if (__supported_pte_mask & _PAGE_NX) 960 961 debug_checkwx(); 961 962 } 962 - #endif 963 -
-3
arch/x86/mm/init_64.c
··· 1074 1074 mem_init_print_info(NULL); 1075 1075 } 1076 1076 1077 - #ifdef CONFIG_DEBUG_RODATA 1078 1077 const int rodata_test_data = 0xC3; 1079 1078 EXPORT_SYMBOL_GPL(rodata_test_data); 1080 1079 ··· 1164 1165 1165 1166 debug_checkwx(); 1166 1167 } 1167 - 1168 - #endif 1169 1168 1170 1169 int kern_addr_valid(unsigned long addr) 1171 1170 {
+1 -1
arch/x86/mm/pageattr.c
··· 283 283 __pa_symbol(__end_rodata) >> PAGE_SHIFT)) 284 284 pgprot_val(forbidden) |= _PAGE_RW; 285 285 286 - #if defined(CONFIG_X86_64) && defined(CONFIG_DEBUG_RODATA) 286 + #if defined(CONFIG_X86_64) 287 287 /* 288 288 * Once the kernel maps the text as RO (kernel_set_to_readonly is set), 289 289 * kernel text mappings for the large page aligned text, rodata sections