diff options
author | Arjan van de Ven <arjan@infradead.org> | 2006-01-06 00:12:02 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-01-06 08:33:36 -0800 |
commit | 63aaf3086baea7b94c218053af8237f9dbac5d05 (patch) | |
tree | dc32bf8878d01a25a321eb6412f27bce7ec7c5b7 | |
parent | 37b73c828185731f6236a6387c02d7b08c150810 (diff) |
[PATCH] x86/x86_64: mark rodata section read only: x86 parts
x86 specific parts to make the .rodata section read only
Signed-off-by: Arjan van de Ven <arjan@infradead.org>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Adrian Bunk <bunk@stusta.de>
Cc: Andi Kleen <ak@muc.de>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r-- | arch/i386/Kconfig.debug | 10 | ||||
-rw-r--r-- | arch/i386/mm/init.c | 24 | ||||
-rw-r--r-- | include/asm-i386/cacheflush.h | 4 |
3 files changed, 38 insertions, 0 deletions
diff --git a/arch/i386/Kconfig.debug b/arch/i386/Kconfig.debug index c48b424dd64..bf32ecc9ad0 100644 --- a/arch/i386/Kconfig.debug +++ b/arch/i386/Kconfig.debug @@ -42,6 +42,16 @@ config DEBUG_PAGEALLOC This results in a large slowdown, but helps to find certain types of memory corruptions. +config DEBUG_RODATA + bool "Write protect kernel read-only data structures" + depends on DEBUG_KERNEL + help + Mark the kernel read-only data as write-protected in the pagetables, + in order to catch accidental (and incorrect) writes to such const + data. This option may have a slight performance impact because a + portion of the kernel code won't be covered by a 2MB TLB anymore. + If in doubt, say "N". + config 4KSTACKS bool "Use 4Kb for kernel stacks instead of 8Kb" depends on DEBUG_KERNEL diff --git a/arch/i386/mm/init.c b/arch/i386/mm/init.c index 06e26f00623..7df494b51a5 100644 --- a/arch/i386/mm/init.c +++ b/arch/i386/mm/init.c @@ -735,6 +735,30 @@ void free_initmem(void) printk (KERN_INFO "Freeing unused kernel memory: %dk freed\n", (__init_end - __init_begin) >> 10); } +#ifdef CONFIG_DEBUG_RODATA + +extern char __start_rodata, __end_rodata; +void mark_rodata_ro(void) +{ + unsigned long addr = (unsigned long)&__start_rodata; + + for (; addr < (unsigned long)&__end_rodata; addr += PAGE_SIZE) + change_page_attr(virt_to_page(addr), 1, PAGE_KERNEL_RO); + + printk ("Write protecting the kernel read-only data: %luk\n", + (unsigned long)(&__end_rodata - &__start_rodata) >> 10); + + /* + * change_page_attr() requires a global_flush_tlb() call after it. + * We do this after the printk so that if something went wrong in the + * change, the printk gets out at least to give a better debug hint + * of who is the culprit. + */ + global_flush_tlb(); +} +#endif + + #ifdef CONFIG_BLK_DEV_INITRD void free_initrd_mem(unsigned long start, unsigned long end) { diff --git a/include/asm-i386/cacheflush.h b/include/asm-i386/cacheflush.h index 2ea36dea37d..7199f7b326f 100644 --- a/include/asm-i386/cacheflush.h +++ b/include/asm-i386/cacheflush.h @@ -31,4 +31,8 @@ int change_page_attr(struct page *page, int numpages, pgprot_t prot); void kernel_map_pages(struct page *page, int numpages, int enable); #endif +#ifdef CONFIG_DEBUG_RODATA +void mark_rodata_ro(void); +#endif + #endif /* _I386_CACHEFLUSH_H */ |