diff options
author | Peter Zijlstra <peterz@infradead.org> | 2020-04-03 19:13:03 +0200 |
---|---|---|
committer | Jessica Yu <jeyu@kernel.org> | 2020-04-21 17:20:13 +0200 |
commit | 5c3a7db0c7ec4bbd5bd3f48af9be859a8fa3e532 (patch) | |
tree | 13901a70e5529cedf2d1ac2dc80230db3d886e77 /kernel | |
parent | module: break nested ARCH_HAS_STRICT_MODULE_RWX and STRICT_MODULE_RWX #ifdefs (diff) | |
download | linux-5c3a7db0c7ec4bbd5bd3f48af9be859a8fa3e532.tar.xz linux-5c3a7db0c7ec4bbd5bd3f48af9be859a8fa3e532.zip |
module: Harden STRICT_MODULE_RWX
We're very close to enforcing W^X memory, refuse to load modules that
violate this principle per construction.
[jeyu: move module_enforce_rwx_sections under STRICT_MODULE_RWX as per discussion]
Link: http://lore.kernel.org/r/20200403171303.GK20760@hirez.programming.kicks-ass.net
Acked-by: Kees Cook <keescook@chromium.org>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Signed-off-by: Jessica Yu <jeyu@kernel.org>
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/module.c | 24 |
1 files changed, 24 insertions, 0 deletions
diff --git a/kernel/module.c b/kernel/module.c index 01d01a489778..70fc20583e66 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -2052,9 +2052,28 @@ static void module_enable_nx(const struct module *mod) frob_writable_data(&mod->init_layout, set_memory_nx); } +static int module_enforce_rwx_sections(Elf_Ehdr *hdr, Elf_Shdr *sechdrs, + char *secstrings, struct module *mod) +{ + const unsigned long shf_wx = SHF_WRITE|SHF_EXECINSTR; + int i; + + for (i = 0; i < hdr->e_shnum; i++) { + if ((sechdrs[i].sh_flags & shf_wx) == shf_wx) + return -ENOEXEC; + } + + return 0; +} + #else /* !CONFIG_STRICT_MODULE_RWX */ /* module_{enable,disable}_ro() stubs are in module.h */ static void module_enable_nx(const struct module *mod) { } +static 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_LIVEPATCH @@ -3385,6 +3404,11 @@ static struct module *layout_and_allocate(struct load_info *info, int flags) if (err < 0) return ERR_PTR(err); + err = module_enforce_rwx_sections(info->hdr, info->sechdrs, + info->secstrings, info->mod); + if (err < 0) + return ERR_PTR(err); + /* We will do a special allocation for per-cpu sections later. */ info->sechdrs[info->index.pcpu].sh_flags &= ~(unsigned long)SHF_ALLOC; |