From: Rick Edgecombe <rick.p.edgecombe@intel.com> To: Andy Lutomirski <luto@kernel.org>, Ingo Molnar <mingo@redhat.com> Cc: linux-kernel@vger.kernel.org, x86@kernel.org, hpa@zytor.com, Thomas Gleixner <tglx@linutronix.de>, Borislav Petkov <bp@alien8.de>, Nadav Amit <nadav.amit@gmail.com>, Dave Hansen <dave.hansen@linux.intel.com>, Peter Zijlstra <peterz@infradead.org>, linux_dti@icloud.com, linux-integrity@vger.kernel.org, linux-security-module@vger.kernel.org, akpm@linux-foundation.org, kernel-hardening@lists.openwall.com, linux-mm@kvack.org, will.deacon@arm.com, ard.biesheuvel@linaro.org, kristen@linux.intel.com, deneen.t.dock@intel.com, Nadav Amit <namit@vmware.com>, Kees Cook <keescook@chromium.org>, Dave Hansen <dave.hansen@intel.com>, Masami Hiramatsu <mhiramat@kernel.org>, Rick Edgecombe <rick.p.edgecombe@intel.com> Subject: [PATCH v2 10/20] x86: avoid W^X being broken during modules loading Date: Mon, 28 Jan 2019 16:34:12 -0800 Message-ID: <20190129003422.9328-11-rick.p.edgecombe@intel.com> (raw) In-Reply-To: <20190129003422.9328-1-rick.p.edgecombe@intel.com> From: Nadav Amit <namit@vmware.com> When modules and BPF filters are loaded, there is a time window in which some memory is both writable and executable. An attacker that has already found another vulnerability (e.g., a dangling pointer) might be able to exploit this behavior to overwrite kernel code. Prevent having writable executable PTEs in this stage. In addition, avoiding having W+X mappings can also slightly simplify the patching of modules code on initialization (e.g., by alternatives and static-key), as would be done in the next patch. To avoid having W+X mappings, set them initially as RW (NX) and after they are set as RO set them as X as well. Setting them as executable is done as a separate step to avoid one core in which the old PTE is cached (hence writable), and another which sees the updated PTE (executable), which would break the W^X protection. Cc: Kees Cook <keescook@chromium.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Dave Hansen <dave.hansen@intel.com> Cc: Masami Hiramatsu <mhiramat@kernel.org> Suggested-by: Thomas Gleixner <tglx@linutronix.de> Suggested-by: Andy Lutomirski <luto@amacapital.net> Signed-off-by: Nadav Amit <namit@vmware.com> Signed-off-by: Rick Edgecombe <rick.p.edgecombe@intel.com> --- arch/x86/kernel/alternative.c | 28 +++++++++++++++++++++------- arch/x86/kernel/module.c | 2 +- include/linux/filter.h | 2 +- kernel/module.c | 5 +++++ 4 files changed, 28 insertions(+), 9 deletions(-) diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c index 76d482a2b716..69f3e650ada8 100644 --- a/arch/x86/kernel/alternative.c +++ b/arch/x86/kernel/alternative.c @@ -667,15 +667,29 @@ void __init alternative_instructions(void) * handlers seeing an inconsistent instruction while you patch. */ void *__init_or_module text_poke_early(void *addr, const void *opcode, - size_t len) + size_t len) { unsigned long flags; - local_irq_save(flags); - memcpy(addr, opcode, len); - local_irq_restore(flags); - sync_core(); - /* Could also do a CLFLUSH here to speed up CPU recovery; but - that causes hangs on some VIA CPUs. */ + + if (static_cpu_has(X86_FEATURE_NX) && + is_module_text_address((unsigned long)addr)) { + /* + * Modules text is marked initially as non-executable, so the + * code cannot be running and speculative code-fetches are + * prevented. We can just change the code. + */ + memcpy(addr, opcode, len); + } else { + local_irq_save(flags); + memcpy(addr, opcode, len); + local_irq_restore(flags); + sync_core(); + + /* + * Could also do a CLFLUSH here to speed up CPU recovery; but + * that causes hangs on some VIA CPUs. + */ + } return addr; } diff --git a/arch/x86/kernel/module.c b/arch/x86/kernel/module.c index b052e883dd8c..cfa3106faee4 100644 --- a/arch/x86/kernel/module.c +++ b/arch/x86/kernel/module.c @@ -87,7 +87,7 @@ void *module_alloc(unsigned long size) p = __vmalloc_node_range(size, MODULE_ALIGN, MODULES_VADDR + get_module_load_offset(), MODULES_END, GFP_KERNEL, - PAGE_KERNEL_EXEC, 0, NUMA_NO_NODE, + PAGE_KERNEL, 0, NUMA_NO_NODE, __builtin_return_address(0)); if (p && (kasan_module_alloc(p, size) < 0)) { vfree(p); diff --git a/include/linux/filter.h b/include/linux/filter.h index d531d4250bff..9cdfab7f383c 100644 --- a/include/linux/filter.h +++ b/include/linux/filter.h @@ -681,7 +681,6 @@ bpf_ctx_narrow_access_ok(u32 off, u32 size, u32 size_default) static inline void bpf_prog_lock_ro(struct bpf_prog *fp) { - fp->undo_set_mem = 1; set_memory_ro((unsigned long)fp, fp->pages); } @@ -694,6 +693,7 @@ static inline void bpf_prog_unlock_ro(struct bpf_prog *fp) static inline void bpf_jit_binary_lock_ro(struct bpf_binary_header *hdr) { set_memory_ro((unsigned long)hdr, hdr->pages); + set_memory_x((unsigned long)hdr, hdr->pages); } static inline void bpf_jit_binary_unlock_ro(struct bpf_binary_header *hdr) diff --git a/kernel/module.c b/kernel/module.c index 2ad1b5239910..ae1b77da6a20 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -1950,8 +1950,13 @@ void module_enable_ro(const struct module *mod, bool after_init) return; frob_text(&mod->core_layout, set_memory_ro); + frob_text(&mod->core_layout, set_memory_x); + frob_rodata(&mod->core_layout, set_memory_ro); + frob_text(&mod->init_layout, set_memory_ro); + frob_text(&mod->init_layout, set_memory_x); + frob_rodata(&mod->init_layout, set_memory_ro); if (after_init) -- 2.17.1
next prev parent reply index Thread overview: 71+ messages / expand[flat|nested] mbox.gz Atom feed top 2019-01-29 0:34 [PATCH v2 00/20] Merge text_poke fixes and executable lockdowns Rick Edgecombe 2019-01-29 0:34 ` [PATCH v2 01/20] Fix "x86/alternatives: Lockdep-enforce text_mutex in text_poke*()" Rick Edgecombe 2019-01-29 0:34 ` [PATCH v2 02/20] x86/jump_label: Use text_poke_early() during early init Rick Edgecombe 2019-01-29 0:34 ` [PATCH v2 03/20] x86/mm: temporary mm struct Rick Edgecombe 2019-01-31 11:29 ` Borislav Petkov 2019-01-31 22:19 ` Nadav Amit 2019-02-01 0:08 ` Borislav Petkov 2019-02-01 0:25 ` Nadav Amit 2019-02-04 14:28 ` Borislav Petkov 2019-01-29 0:34 ` [PATCH v2 04/20] fork: provide a function for copying init_mm Rick Edgecombe 2019-02-05 8:53 ` Borislav Petkov 2019-02-05 9:03 ` Nadav Amit 2019-01-29 0:34 ` [PATCH v2 05/20] x86/alternative: initializing temporary mm for patching Rick Edgecombe 2019-02-05 9:18 ` Borislav Petkov 2019-02-11 0:39 ` Nadav Amit 2019-02-11 5:18 ` Andy Lutomirski 2019-02-11 18:04 ` Nadav Amit 2019-02-11 19:07 ` Andy Lutomirski 2019-02-11 19:18 ` Nadav Amit 2019-02-11 22:47 ` Andy Lutomirski 2019-02-12 18:23 ` Nadav Amit 2019-01-29 0:34 ` [PATCH v2 06/20] x86/alternative: use temporary mm for text poking Rick Edgecombe 2019-02-05 9:58 ` Borislav Petkov 2019-02-05 11:31 ` Peter Zijlstra 2019-02-05 12:35 ` Borislav Petkov 2019-02-05 13:25 ` Peter Zijlstra 2019-02-05 17:54 ` Nadav Amit 2019-02-05 13:29 ` Peter Zijlstra 2019-01-29 0:34 ` [PATCH v2 07/20] x86/kgdb: avoid redundant comparison of patched code Rick Edgecombe 2019-01-29 0:34 ` [PATCH v2 08/20] x86/ftrace: set trampoline pages as executable Rick Edgecombe 2019-01-29 0:34 ` [PATCH v2 09/20] x86/kprobes: instruction pages initialization enhancements Rick Edgecombe 2019-02-11 18:22 ` Borislav Petkov 2019-02-11 19:36 ` Nadav Amit 2019-01-29 0:34 ` Rick Edgecombe [this message] 2019-02-11 18:29 ` [PATCH v2 10/20] x86: avoid W^X being broken during modules loading Borislav Petkov 2019-02-11 18:45 ` Nadav Amit 2019-02-11 19:01 ` Borislav Petkov 2019-02-11 19:09 ` Nadav Amit 2019-02-11 19:10 ` Borislav Petkov 2019-02-11 19:27 ` Nadav Amit 2019-02-11 19:42 ` Borislav Petkov 2019-02-11 20:32 ` Nadav Amit 2019-03-07 15:10 ` [PATCH] x86/cpufeature: Remove __pure attribute to _static_cpu_has() Borislav Petkov 2019-03-07 16:43 ` hpa 2019-03-07 17:02 ` Borislav Petkov 2019-03-07 7:29 ` [PATCH v2 10/20] x86: avoid W^X being broken during modules loading Borislav Petkov 2019-03-07 16:53 ` hpa 2019-03-07 17:06 ` Borislav Petkov 2019-03-07 20:02 ` Andy Lutomirski 2019-03-07 20:25 ` Borislav Petkov 2019-01-29 0:34 ` [PATCH v2 11/20] x86/jump-label: remove support for custom poker Rick Edgecombe 2019-02-11 18:37 ` Borislav Petkov 2019-01-29 0:34 ` [PATCH v2 12/20] x86/alternative: Remove the return value of text_poke_*() Rick Edgecombe 2019-01-29 0:34 ` [PATCH v2 13/20] Add set_alias_ function and x86 implementation Rick Edgecombe 2019-02-11 19:09 ` Borislav Petkov 2019-02-11 19:27 ` Edgecombe, Rick P 2019-02-11 22:59 ` Andy Lutomirski 2019-02-12 0:01 ` Edgecombe, Rick P 2019-01-29 0:34 ` [PATCH v2 14/20] mm: Make hibernate handle unmapped pages Rick Edgecombe 2019-02-19 11:04 ` Borislav Petkov 2019-02-19 21:28 ` Edgecombe, Rick P 2019-02-20 16:07 ` Borislav Petkov 2019-01-29 0:34 ` [PATCH v2 15/20] vmalloc: New flags for safe vfree on special perms Rick Edgecombe 2019-02-19 12:48 ` Borislav Petkov 2019-02-19 19:42 ` Edgecombe, Rick P 2019-02-20 16:14 ` Borislav Petkov 2019-01-29 0:34 ` [PATCH v2 16/20] modules: Use vmalloc special flag Rick Edgecombe 2019-01-29 0:34 ` [PATCH v2 17/20] bpf: " Rick Edgecombe 2019-01-29 0:34 ` [PATCH v2 18/20] x86/ftrace: " Rick Edgecombe 2019-01-29 0:34 ` [PATCH v2 19/20] x86/kprobes: " Rick Edgecombe 2019-01-29 0:34 ` [PATCH v2 20/20] x86/alternative: comment about module removal races Rick Edgecombe
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=20190129003422.9328-11-rick.p.edgecombe@intel.com \ --to=rick.p.edgecombe@intel.com \ --cc=akpm@linux-foundation.org \ --cc=ard.biesheuvel@linaro.org \ --cc=bp@alien8.de \ --cc=dave.hansen@intel.com \ --cc=dave.hansen@linux.intel.com \ --cc=deneen.t.dock@intel.com \ --cc=hpa@zytor.com \ --cc=keescook@chromium.org \ --cc=kernel-hardening@lists.openwall.com \ --cc=kristen@linux.intel.com \ --cc=linux-integrity@vger.kernel.org \ --cc=linux-kernel@vger.kernel.org \ --cc=linux-mm@kvack.org \ --cc=linux-security-module@vger.kernel.org \ --cc=linux_dti@icloud.com \ --cc=luto@kernel.org \ --cc=mhiramat@kernel.org \ --cc=mingo@redhat.com \ --cc=nadav.amit@gmail.com \ --cc=namit@vmware.com \ --cc=peterz@infradead.org \ --cc=tglx@linutronix.de \ --cc=will.deacon@arm.com \ --cc=x86@kernel.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: link
Linux-Integrity Archive on lore.kernel.org Archives are clonable: git clone --mirror https://lore.kernel.org/linux-integrity/0 linux-integrity/git/0.git # If you have public-inbox 1.1+ installed, you may # initialize and index your mirror using the following commands: public-inbox-init -V2 linux-integrity linux-integrity/ https://lore.kernel.org/linux-integrity \ linux-integrity@vger.kernel.org public-inbox-index linux-integrity Example config snippet for mirrors Newsgroup available over NNTP: nntp://nntp.lore.kernel.org/org.kernel.vger.linux-integrity AGPL code for this site: git clone https://public-inbox.org/public-inbox.git