| From e4cb269c974c1fea2b95cfde5d0860c261a041d5 Mon Sep 17 00:00:00 2001 |
| From: Nadav Amit <namit@vmware.com> |
| Date: Thu, 25 Apr 2019 17:11:30 -0700 |
| Subject: x86/kprobes: Set instruction page as executable |
| |
| [ Upstream commit 7298e24f904224fa79eb8fd7e0fbd78950ccf2db ] |
| |
| Set the page as executable after allocation. This patch is a |
| preparatory patch for a following patch that makes module allocated |
| pages non-executable. |
| |
| While at it, do some small cleanup of what appears to be unnecessary |
| masking. |
| |
| Signed-off-by: Nadav Amit <namit@vmware.com> |
| Signed-off-by: Rick Edgecombe <rick.p.edgecombe@intel.com> |
| Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> |
| Cc: <akpm@linux-foundation.org> |
| Cc: <ard.biesheuvel@linaro.org> |
| Cc: <deneen.t.dock@intel.com> |
| Cc: <kernel-hardening@lists.openwall.com> |
| Cc: <kristen@linux.intel.com> |
| Cc: <linux_dti@icloud.com> |
| Cc: <will.deacon@arm.com> |
| Cc: Andy Lutomirski <luto@kernel.org> |
| Cc: Borislav Petkov <bp@alien8.de> |
| Cc: Dave Hansen <dave.hansen@linux.intel.com> |
| Cc: H. Peter Anvin <hpa@zytor.com> |
| Cc: Linus Torvalds <torvalds@linux-foundation.org> |
| Cc: Rik van Riel <riel@surriel.com> |
| Cc: Thomas Gleixner <tglx@linutronix.de> |
| Link: https://lkml.kernel.org/r/20190426001143.4983-11-namit@vmware.com |
| Signed-off-by: Ingo Molnar <mingo@kernel.org> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| arch/x86/kernel/kprobes/core.c | 24 ++++++++++++++++++++---- |
| 1 file changed, 20 insertions(+), 4 deletions(-) |
| |
| diff --git a/arch/x86/kernel/kprobes/core.c b/arch/x86/kernel/kprobes/core.c |
| index 544bc2dfe408..e83a057564d1 100644 |
| --- a/arch/x86/kernel/kprobes/core.c |
| +++ b/arch/x86/kernel/kprobes/core.c |
| @@ -431,8 +431,20 @@ void *alloc_insn_page(void) |
| void *page; |
| |
| page = module_alloc(PAGE_SIZE); |
| - if (page) |
| - set_memory_ro((unsigned long)page & PAGE_MASK, 1); |
| + if (!page) |
| + return NULL; |
| + |
| + /* |
| + * First make the page read-only, and only then make it executable to |
| + * prevent it from being W+X in between. |
| + */ |
| + set_memory_ro((unsigned long)page, 1); |
| + |
| + /* |
| + * TODO: Once additional kernel code protection mechanisms are set, ensure |
| + * that the page was not maliciously altered and it is still zeroed. |
| + */ |
| + set_memory_x((unsigned long)page, 1); |
| |
| return page; |
| } |
| @@ -440,8 +452,12 @@ void *alloc_insn_page(void) |
| /* Recover page to RW mode before releasing it */ |
| void free_insn_page(void *page) |
| { |
| - set_memory_nx((unsigned long)page & PAGE_MASK, 1); |
| - set_memory_rw((unsigned long)page & PAGE_MASK, 1); |
| + /* |
| + * First make the page non-executable, and only then make it writable to |
| + * prevent it from being W+X in between. |
| + */ |
| + set_memory_nx((unsigned long)page, 1); |
| + set_memory_rw((unsigned long)page, 1); |
| module_memfree(page); |
| } |
| |
| -- |
| 2.20.1 |
| |