diff options
author | Christophe Leroy <christophe.leroy@csgroup.eu> | 2022-02-23 12:00:59 +0300 |
---|---|---|
committer | Luis Chamberlain <mcgrof@kernel.org> | 2022-04-05 18:43:04 +0300 |
commit | 32a08c17d8096f0fd2c6600bc5fe8464aaf68ea7 (patch) | |
tree | ca8c7a86bf5a6a83cf56d96f1cdf42353dd28dd3 /kernel/module | |
parent | 0597579356fe5b6c0b99196e4743d4c2978f654a (diff) | |
download | linux-32a08c17d8096f0fd2c6600bc5fe8464aaf68ea7.tar.xz |
module: Move module_enable_x() and frob_text() in strict_rwx.c
Move module_enable_x() together with module_enable_nx() and
module_enable_ro().
Those three functions are going together, they are all used
to set up the correct page flags on the different sections.
As module_enable_x() is used independently of
CONFIG_STRICT_MODULE_RWX, build strict_rwx.c all the time and
use IS_ENABLED(CONFIG_STRICT_MODULE_RWX) when relevant.
Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu>
Signed-off-by: Luis Chamberlain <mcgrof@kernel.org>
Diffstat (limited to 'kernel/module')
-rw-r--r-- | kernel/module/Makefile | 3 | ||||
-rw-r--r-- | kernel/module/internal.h | 15 | ||||
-rw-r--r-- | kernel/module/main.c | 37 | ||||
-rw-r--r-- | kernel/module/strict_rwx.c | 48 |
4 files changed, 50 insertions, 53 deletions
diff --git a/kernel/module/Makefile b/kernel/module/Makefile index e2eff9853a28..d1ca799c12e2 100644 --- a/kernel/module/Makefile +++ b/kernel/module/Makefile @@ -7,12 +7,11 @@ # and produce insane amounts of uninteresting coverage. KCOV_INSTRUMENT_module.o := n -obj-y += main.o +obj-y += main.o strict_rwx.o obj-$(CONFIG_MODULE_DECOMPRESS) += decompress.o obj-$(CONFIG_MODULE_SIG) += signing.o obj-$(CONFIG_LIVEPATCH) += livepatch.o obj-$(CONFIG_MODULES_TREE_LOOKUP) += tree_lookup.o -obj-$(CONFIG_STRICT_MODULE_RWX) += strict_rwx.o obj-$(CONFIG_DEBUG_KMEMLEAK) += debug_kmemleak.o obj-$(CONFIG_KALLSYMS) += kallsyms.o obj-$(CONFIG_PROC_FS) += procfs.o diff --git a/kernel/module/internal.h b/kernel/module/internal.h index 972bc811dcd2..c59473b232df 100644 --- a/kernel/module/internal.h +++ b/kernel/module/internal.h @@ -175,25 +175,12 @@ static inline struct module *mod_find(unsigned long addr) } #endif /* CONFIG_MODULES_TREE_LOOKUP */ -void frob_text(const struct module_layout *layout, int (*set_memory)(unsigned long start, - int num_pages)); - -#ifdef CONFIG_STRICT_MODULE_RWX void module_enable_ro(const struct module *mod, bool after_init); void module_enable_nx(const struct module *mod); +void module_enable_x(const struct module *mod); int module_enforce_rwx_sections(Elf_Ehdr *hdr, Elf_Shdr *sechdrs, char *secstrings, struct module *mod); -#else /* !CONFIG_STRICT_MODULE_RWX */ -static inline void module_enable_nx(const struct module *mod) { } -static inline void module_enable_ro(const struct module *mod, bool after_init) {} -static inline int module_enforce_rwx_sections(Elf_Ehdr *hdr, Elf_Shdr *sechdrs, - char *secstrings, struct module *mod) -{ - return 0; -} -#endif /* CONFIG_STRICT_MODULE_RWX */ - #ifdef CONFIG_MODULE_SIG int module_sig_check(struct load_info *info, int flags); #else /* !CONFIG_MODULE_SIG */ diff --git a/kernel/module/main.c b/kernel/module/main.c index 2bf8c617a901..7175b44ba88a 100644 --- a/kernel/module/main.c +++ b/kernel/module/main.c @@ -1124,43 +1124,6 @@ resolve_symbol_wait(struct module *mod, return ksym; } -/* - * LKM RO/NX protection: protect module's text/ro-data - * from modification and any data from execution. - * - * General layout of module is: - * [text] [read-only-data] [ro-after-init] [writable data] - * text_size -----^ ^ ^ ^ - * ro_size ------------------------| | | - * ro_after_init_size -----------------------------| | - * size -----------------------------------------------------------| - * - * These values are always page-aligned (as is base) - */ - -/* - * Since some arches are moving towards PAGE_KERNEL module allocations instead - * of PAGE_KERNEL_EXEC, keep frob_text() and module_enable_x() outside of the - * CONFIG_STRICT_MODULE_RWX block below because they are needed regardless of - * whether we are strict. - */ -void frob_text(const struct module_layout *layout, - int (*set_memory)(unsigned long start, int num_pages)) -{ - set_memory((unsigned long)layout->base, - PAGE_ALIGN(layout->text_size) >> PAGE_SHIFT); -} - -static void module_enable_x(const struct module *mod) -{ - if (!PAGE_ALIGNED(mod->core_layout.base) || - !PAGE_ALIGNED(mod->init_layout.base)) - return; - - frob_text(&mod->core_layout, set_memory_x); - frob_text(&mod->init_layout, set_memory_x); -} - void __weak module_memfree(void *module_region) { /* diff --git a/kernel/module/strict_rwx.c b/kernel/module/strict_rwx.c index 7949dfd449c2..43332b4416b0 100644 --- a/kernel/module/strict_rwx.c +++ b/kernel/module/strict_rwx.c @@ -11,6 +11,34 @@ #include <linux/set_memory.h> #include "internal.h" +/* + * LKM RO/NX protection: protect module's text/ro-data + * from modification and any data from execution. + * + * General layout of module is: + * [text] [read-only-data] [ro-after-init] [writable data] + * text_size -----^ ^ ^ ^ + * ro_size ------------------------| | | + * ro_after_init_size -----------------------------| | + * size -----------------------------------------------------------| + * + * These values are always page-aligned (as is base) when + * CONFIG_STRICT_MODULE_RWX is set. + */ + +/* + * Since some arches are moving towards PAGE_KERNEL module allocations instead + * of PAGE_KERNEL_EXEC, keep frob_text() and module_enable_x() independent of + * CONFIG_STRICT_MODULE_RWX because they are needed regardless of whether we + * are strict. + */ +static void frob_text(const struct module_layout *layout, + int (*set_memory)(unsigned long start, int num_pages)) +{ + set_memory((unsigned long)layout->base, + PAGE_ALIGN(layout->text_size) >> PAGE_SHIFT); +} + static void frob_rodata(const struct module_layout *layout, int (*set_memory)(unsigned long start, int num_pages)) { @@ -41,10 +69,24 @@ static void frob_writable_data(const struct module_layout *layout, (layout->size - layout->ro_after_init_size) >> PAGE_SHIFT); } +void module_enable_x(const struct module *mod) +{ + if (!PAGE_ALIGNED(mod->core_layout.base) || + !PAGE_ALIGNED(mod->init_layout.base)) + return; + + frob_text(&mod->core_layout, set_memory_x); + frob_text(&mod->init_layout, set_memory_x); +} + void module_enable_ro(const struct module *mod, bool after_init) { + if (!IS_ENABLED(CONFIG_STRICT_MODULE_RWX)) + return; +#ifdef CONFIG_STRICT_MODULE_RWX if (!rodata_enabled) return; +#endif set_vm_flush_reset_perms(mod->core_layout.base); set_vm_flush_reset_perms(mod->init_layout.base); @@ -60,6 +102,9 @@ void module_enable_ro(const struct module *mod, bool after_init) void module_enable_nx(const struct module *mod) { + if (!IS_ENABLED(CONFIG_STRICT_MODULE_RWX)) + return; + frob_rodata(&mod->core_layout, set_memory_nx); frob_ro_after_init(&mod->core_layout, set_memory_nx); frob_writable_data(&mod->core_layout, set_memory_nx); @@ -73,6 +118,9 @@ int module_enforce_rwx_sections(Elf_Ehdr *hdr, Elf_Shdr *sechdrs, const unsigned long shf_wx = SHF_WRITE | SHF_EXECINSTR; int i; + if (!IS_ENABLED(CONFIG_STRICT_MODULE_RWX)) + return 0; + for (i = 0; i < hdr->e_shnum; i++) { if ((sechdrs[i].sh_flags & shf_wx) == shf_wx) { pr_err("%s: section %s (index %d) has invalid WRITE|EXEC flags\n", |