forked from mirrors/linux
		
	mm/init: Add 'rodata=off' boot cmdline parameter to disable read-only kernel mappings
It may be useful to debug writes to the readonly sections of memory, so provide a cmdline "rodata=off" to allow for this. This can be expanded in the future to support "log" and "write" modes, but that will need to be architecture-specific. This also makes KDB software breakpoints more usable, as read-only mappings can now be disabled on any kernel. Suggested-by: H. Peter Anvin <hpa@zytor.com> 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: 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-3-git-send-email-keescook@chromium.org Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:
		
							parent
							
								
									e267d97b83
								
							
						
					
					
						commit
						d2aa1acad2
					
				
					 3 changed files with 28 additions and 7 deletions
				
			
		|  | @ -3491,6 +3491,10 @@ bytes respectively. Such letter suffixes can also be entirely omitted. | ||||||
| 
 | 
 | ||||||
| 	ro		[KNL] Mount root device read-only on boot | 	ro		[KNL] Mount root device read-only on boot | ||||||
| 
 | 
 | ||||||
|  | 	rodata=		[KNL] | ||||||
|  | 		on	Mark read-only kernel memory as read-only (default). | ||||||
|  | 		off	Leave read-only kernel memory writable for debugging. | ||||||
|  | 
 | ||||||
| 	root=		[KNL] Root filesystem | 	root=		[KNL] Root filesystem | ||||||
| 			See name_to_dev_t comment in init/do_mounts.c. | 			See name_to_dev_t comment in init/do_mounts.c. | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
							
								
								
									
										27
									
								
								init/main.c
									
									
									
									
									
								
							
							
						
						
									
										27
									
								
								init/main.c
									
									
									
									
									
								
							|  | @ -93,9 +93,6 @@ static int kernel_init(void *); | ||||||
| extern void init_IRQ(void); | extern void init_IRQ(void); | ||||||
| extern void fork_init(void); | extern void fork_init(void); | ||||||
| extern void radix_tree_init(void); | extern void radix_tree_init(void); | ||||||
| #ifndef CONFIG_DEBUG_RODATA |  | ||||||
| static inline void mark_rodata_ro(void) { } |  | ||||||
| #endif |  | ||||||
| 
 | 
 | ||||||
| /*
 | /*
 | ||||||
|  * Debug helper: via this flag we know that we are in 'early bootup code' |  * Debug helper: via this flag we know that we are in 'early bootup code' | ||||||
|  | @ -929,6 +926,28 @@ static int try_to_run_init_process(const char *init_filename) | ||||||
| 
 | 
 | ||||||
| static noinline void __init kernel_init_freeable(void); | static noinline void __init kernel_init_freeable(void); | ||||||
| 
 | 
 | ||||||
|  | #ifdef CONFIG_DEBUG_RODATA | ||||||
|  | static bool rodata_enabled = true; | ||||||
|  | static int __init set_debug_rodata(char *str) | ||||||
|  | { | ||||||
|  | 	return strtobool(str, &rodata_enabled); | ||||||
|  | } | ||||||
|  | __setup("rodata=", set_debug_rodata); | ||||||
|  | 
 | ||||||
|  | static void mark_readonly(void) | ||||||
|  | { | ||||||
|  | 	if (rodata_enabled) | ||||||
|  | 		mark_rodata_ro(); | ||||||
|  | 	else | ||||||
|  | 		pr_info("Kernel memory protection disabled.\n"); | ||||||
|  | } | ||||||
|  | #else | ||||||
|  | static inline void mark_readonly(void) | ||||||
|  | { | ||||||
|  | 	pr_warn("This architecture does not have kernel memory protection.\n"); | ||||||
|  | } | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
| static int __ref kernel_init(void *unused) | static int __ref kernel_init(void *unused) | ||||||
| { | { | ||||||
| 	int ret; | 	int ret; | ||||||
|  | @ -937,7 +956,7 @@ static int __ref kernel_init(void *unused) | ||||||
| 	/* need to finish all async __init code before freeing the memory */ | 	/* need to finish all async __init code before freeing the memory */ | ||||||
| 	async_synchronize_full(); | 	async_synchronize_full(); | ||||||
| 	free_initmem(); | 	free_initmem(); | ||||||
| 	mark_rodata_ro(); | 	mark_readonly(); | ||||||
| 	system_state = SYSTEM_RUNNING; | 	system_state = SYSTEM_RUNNING; | ||||||
| 	numa_default_policy(); | 	numa_default_policy(); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -153,13 +153,11 @@ static int _kdb_bp_install(struct pt_regs *regs, kdb_bp_t *bp) | ||||||
| 	} else { | 	} else { | ||||||
| 		kdb_printf("%s: failed to set breakpoint at 0x%lx\n", | 		kdb_printf("%s: failed to set breakpoint at 0x%lx\n", | ||||||
| 			   __func__, bp->bp_addr); | 			   __func__, bp->bp_addr); | ||||||
| #ifdef CONFIG_DEBUG_RODATA |  | ||||||
| 		if (!bp->bp_type) { | 		if (!bp->bp_type) { | ||||||
| 			kdb_printf("Software breakpoints are unavailable.\n" | 			kdb_printf("Software breakpoints are unavailable.\n" | ||||||
| 				   "  Change the kernel CONFIG_DEBUG_RODATA=n\n" | 				   "  Boot the kernel with rodata=off\n" | ||||||
| 				   "  OR use hw breaks: help bph\n"); | 				   "  OR use hw breaks: help bph\n"); | ||||||
| 		} | 		} | ||||||
| #endif |  | ||||||
| 		return 1; | 		return 1; | ||||||
| 	} | 	} | ||||||
| 	return 0; | 	return 0; | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue
	
	 Kees Cook
						Kees Cook