RO/NX protection for loadable kernel modules
Subsystems (4)
PATCH v10 1/1 RO/NX protection for loadable kernel modules
This patch is a logical extension of the protection provided by CONFIG_DEBUG_RODATA to LKMs. The protection is provided by splitting module_core and module_init into three logical parts each and setting appropriate page access permissions for each individual section:
1. Code: RO+X
2. RO data: RO+NX
3. RW data: RW+NX
In order to achieve proper protection, layout_sections() have been modified to align each of the three parts mentioned above onto page boundary. Next, the corresponding page access permissions are set right before successful exit from load_module(). Further, free_module() and sys_init_module have been modified to set module_core and module_init as RW+NX right before calling module_free().
By default, the original section layout and access flags are preserved. When compiled with CONFIG_DEBUG_SET_MODULE_RONX=y, the patch will page-align each group of sections to ensure that each page contains only one type of content and will enforce RO/NX for each group of pages.
V1: Initial proof-of-concept patch.
V2: The patch have been re-written to reduce the number of #ifdefs and to make it architecture-agnostic. Code formatting have been corrected also.
V3: Opportunistic RO/NX protectiuon is now unconditional. Section page-alignment is enabled when CONFIG_DEBUG_RODATA=y.
V4: Removed most macros and improved coding style.
V5: Changed page-alignment and RO/NX section size calculation
V6: Fixed comments. Restricted RO/NX enforcement to x86 only
V7: Introduced CONFIG_DEBUG_SET_MODULE_RONX, added calls to set_all_modules_text_rw() and set_all_modules_text_ro() in ftrace
V8: updated for compatibility with linux 2.6.33-rc5
V9: coding style fixes
V10: more coding style fixes
The patch have been developed for Linux 2.6.33-rc5 by Siarhei Liakh <[email protected]> and Xuxian Jiang <[email protected]>.
---
arch/x86/Kconfig.debug +11 -0
@@ -115,6 +115,17 @@ config DEBUG_RODATA_TEST feature as well as for the change_page_attr() infrastructure. If in doubt, say "N" +config DEBUG_SET_MODULE_RONX + bool "Set loadable kernel module data as NX and text as RO" + default n + depends on X86 && MODULES + ---help--- + This option helps to catch unintended modifications to loadable + kernel module's text and read-only data. It also prevents execution + of LKM's data. Such protection may interfere with run-time code + patching and dynamic kernel tracing. + If in doubt, say "N". + config DEBUG_NX_TEST tristate "Testcase for the NX non-executable stack feature" depends on DEBUG_KERNEL && m
arch/x86/kernel/ftrace.c +3 -1
@@ -19,6 +19,7 @@#include <linux/sched.h> #include <linux/init.h> #include <linux/list.h> +#include <linux/module.h> #include <trace/syscall.h>
@@ -29,16 +30,17 @@#ifdef CONFIG_DYNAMIC_FTRACE -int ftrace_arch_code_modify_prepare (void ) {set_kernel_text_rw (); +set_all_modules_text_rw ();return 0 ; }int ftrace_arch_code_modify_post_process (void ) {set_kernel_text_ro (); +set_all_modules_text_ro ();return 0 ; }
include/linux/module.h +6 -0
@@ -300,6 +300,9 @@ struct module/* The size of the executable code in each section. */ unsigned int init_text_size, core_text_size; +/* Size of RO sections of the module (text+rodata) */ +unsigned int init_ro_size, core_ro_size; +/* Arch-specific module values */ struct mod_arch_specific arch;
@@ -542,6 +545,9 @@ extern void print_modules(void);extern void module_update_tracepoints (void );extern int module_get_iter_tracepoints (struct tracepoint_iter *iter); +void set_all_modules_text_rw (void ); +void set_all_modules_text_ro (void ); +#else /* !CONFIG_MODULES... */ #define EXPORT_SYMBOL (sym)#define EXPORT_SYMBOL_GPL (sym)
@@ -662,6 +668,13 @@ static inline int
module_get_iter_tracepoints(struct tracepoint_iter *iter)
return 0;
}
+static inline void set_all_modules_text_rw()
+{
+}
+
+static inline void set_all_modules_text_ro()
+{
+}
#endif /* CONFIG_MODULES */
struct device_driver;
kernel/module.c +167 -2
213 lines not on this page · raw message
__user *umod,
trace_module_load(mod);
+ /* Set RO and NX regions for core */
+ set_section_ro_nx(mod->module_core,
+ mod->core_text_size,
+ mod->core_ro_size,
+ mod->core_size);
+
+ /* Set RO and NX regions for init */
+ set_section_ro_nx(mod->module_init,
+ mod->init_text_size,
+ mod->init_ro_size,
+ mod->init_size);
+
/* Done! */
return mod;
@@ -2504,6 +2681,7 @@ SYSCALL_DEFINE3(init_module, void __user *, umod,
mod->symtab = mod->core_symtab;
mod->strtab = mod->core_strtab;
#endif
+ unset_section_ro_nx(mod, mod->module_init);
module_free(mod, mod->module_init);
mod->module_init = NULL;
mod->init_size = 0;
Rusty Russell
AppliedQuoted 8 lines · Siarhei Liakh
This patch is a logical extension of the protection provided by
CONFIG_DEBUG_RODATAto LKMs. The protection is provided by splittingmodule_coreandmodule_initinto three logical parts each and setting appropriate page access permissions for each individual section:1. Code: RO+X
2. RO data: RO+NX
3. RW data: RW+NX
Thanks, applied!
Cheers,
Rusty.
H. Peter Anvin
reviewerQuoted 11 lines · Rusty Russell
Quoted 8 lines · Siarhei Liakh
This patch is a logical extension of the protection provided by
CONFIG_DEBUG_RODATAto LKMs. The protection is provided by splittingmodule_coreandmodule_initinto three logical parts each and setting appropriate page access permissions for each individual section:1. Code: RO+X
2. RO data: RO+NX
3. RW data: RW+NXThanks, applied!
I also applied this to the -tip tree... do you prefer to carry it or should I leave it as is?
-hpa
Rusty Russell
Acked-byQuoted 7 lines · H. Peter Anvin
Quoted 6 lines · Rusty Russell
Quoted 5 lines · Siarhei Liakh
This patch is a logical extension of the protection provided by
CONFIG_DEBUG_RODATAto LKMs. The protection is provided by splittingmodule_coreandmodule_initinto three logical parts each and setting appropriate page access permissions for each individual section:
Quoted 8 lines
Quoted 5 lines
Quoted 3 lines
1. Code: RO+X
2. RO data: RO+NX
3. RW data: RW+NXThanks, applied!
I also applied this to the -tip tree... do you prefer to carry it or should I leave it as is?
I'm always happy for you to do my work for me! There are no other module patches likely to conflict.
Cheers,
Rusty.
Hi,
Quoted 14 lines · Rusty Russell
Quoted 13 lines · H. Peter Anvin
Quoted 11 lines · Rusty Russell
Quoted 8 lines · Siarhei Liakh
This patch is a logical extension of the protection provided by
CONFIG_DEBUG_RODATAto LKMs. The protection is provided by splittingmodule_coreandmodule_initinto three logical parts each and setting appropriate page access permissions for each individual section:1. Code: RO+X
2. RO data: RO+NX
3. RW data: RW+NXThanks, applied!
Quoted 7 lines
Quoted 2 lines
I also applied this to the -tip tree... do you prefer to carry it or should I leave it as is?
I'm always happy for you to do my work for me! There are no other module patches likely to conflict.
Acked-by Rusty Russell <[email protected]>
Sorry for losing track, but where did this patch end up? I don't see it in any of the trees I've looked in.
Thanks,
-Kees
Signature · 2 lines
Kees Cook Ubuntu Security Team
Quoted 1 line · Kees Cook
Hi,
...
Quoted 2 lines
Sorry for losing track, but where did this patch end up? I don't see it in any of the trees I've looked in.
Good question... This would be quite nice to have of course.
Rusty.
[tip:x86/mm] x86: RO/NX protection for loadable kernel modules
In reply to Siarhei LiakhCommit-ID: 65187d24fa3ef60f691f847c792e8eaca7e19251 Gitweb: http://git.kernel.org/tip/65187d24fa3ef60f691f847c792e8eaca7e19251 Author: Siarhei Liakh <[email protected]> AuthorDate: Mon, 1 Feb 2010 18:39:53 -0500 Committer: H. Peter Anvin <[email protected]> CommitDate: Wed, 17 Feb 2010 10:11:24 -0800
x86: RO/NX protection for loadable kernel modules
This patch is a logical extension of the protection provided by CONFIG_DEBUG_RODATA to LKMs. The protection is provided by splitting module_core and module_init into three logical parts each and setting appropriate page access permissions for each individual section:
1. Code: RO+X
2. RO data: RO+NX
3. RW data: RW+NX
In order to achieve proper protection, layout_sections() have been modified to align each of the three parts mentioned above onto page boundary. Next, the corresponding page access permissions are set right before successful exit from load_module(). Further, free_module() and sys_init_module have been modified to set module_core and module_init as RW+NX right before calling module_free().
By default, the original section layout and access flags are preserved. When compiled with CONFIG_DEBUG_SET_MODULE_RONX=y, the patch will page-align each group of sections to ensure that each page contains only one type of content and will enforce RO/NX for each group of pages.
V1: Initial proof-of-concept patch.
V2: The patch have been re-written to reduce the number of #ifdefs and to make it architecture-agnostic. Code formatting have been corrected also.
V3: Opportunistic RO/NX protectiuon is now unconditional. Section page-alignment is enabled when CONFIG_DEBUG_RODATA=y.
V4: Removed most macros and improved coding style.
V5: Changed page-alignment and RO/NX section size calculation
V6: Fixed comments. Restricted RO/NX enforcement to x86 only
V7: Introduced CONFIG_DEBUG_SET_MODULE_RONX, added calls to set_all_modules_text_rw() and set_all_modules_text_ro() in ftrace
V8: updated for compatibility with linux 2.6.33-rc5
V9: coding style fixes
V10: more coding style fixes
LKML-Reference: <[email protected]>
--- arch/x86/Kconfig.debug | 11 +++ arch/x86/kernel/ftrace.c | 4 +- include/linux/module.h | 13 +++ kernel/module.c | 182 +++++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 207 insertions(+), 3 deletions(-)
arch/x86/Kconfig.debug +11 -0
@@ -115,6 +115,17 @@ config DEBUG_RODATA_TEST feature as well as for the change_page_attr() infrastructure. If in doubt, say "N" +config DEBUG_SET_MODULE_RONX + bool "Set loadable kernel module data as NX and text as RO" + default n + depends on X86 && MODULES + ---help--- + This option helps to catch unintended modifications to loadable + kernel module's text and read-only data. It also prevents execution + of LKM's data. Such protection may interfere with run-time code + patching and dynamic kernel tracing. + If in doubt, say "N". + config DEBUG_NX_TEST tristate "Testcase for the NX non-executable stack feature" depends on DEBUG_KERNEL && m
arch/x86/kernel/ftrace.c +3 -1
@@ -19,6 +19,7 @@#include <linux/sched.h> #include <linux/init.h> #include <linux/list.h> +#include <linux/module.h> #include <trace/syscall.h>
@@ -29,16 +30,17 @@#ifdef CONFIG_DYNAMIC_FTRACE -int ftrace_arch_code_modify_prepare (void ) {set_kernel_text_rw (); +set_all_modules_text_rw ();return 0 ; }int ftrace_arch_code_modify_post_process (void ) {set_kernel_text_ro (); +set_all_modules_text_ro ();return 0 ; }
include/linux/module.h +13 -0
@@ -300,6 +300,9 @@ struct module/* The size of the executable code in each section. */ unsigned int init_text_size, core_text_size; +/* Size of RO sections of the module (text+rodata) */ +unsigned int init_ro_size, core_ro_size; +/* Arch-specific module values */ struct mod_arch_specific arch;
@@ -542,6 +545,9 @@ extern void print_modules(void);extern void module_update_tracepoints (void );extern int module_get_iter_tracepoints (struct tracepoint_iter *iter); +void set_all_modules_text_rw (void ); +void set_all_modules_text_ro (void ); +#else /* !CONFIG_MODULES... */ #define EXPORT_SYMBOL (sym)#define EXPORT_SYMBOL_GPL (sym)
@@ -662,6 +668,13 @@ static inline int module_get_iter_tracepoints(struct tracepoint_iter *iter) return 0; } +static inline void set_all_modules_text_rw () +{ +} + +static inline void set_all_modules_text_ro () +{ +}#endif /* CONFIG_MODULES */ struct device_driver ;
kernel/module.c +180 -2
238 lines not on this page · raw message