x86/kprobes: Set instruction page as executable [Linux 5.1.8]

x86/kprobes: Set instruction page as executable [Linux 5.1.8]

This Linux kernel change "x86/kprobes: Set instruction page as executable" is included in the Linux 5.1.8 release. This change is authored by Nadav Amit <namit [at] vmware.com> on Thu Apr 25 17:11:30 2019 -0700. The commit for this change in Linux stable tree is 94395ad (patch) which is from upstream commit 7298e24. The same Linux upstream change may have been applied to various maintained Linux releases and you can find all Linux releases containing changes from upstream 7298e24.

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>

There are 24 lines of Linux source code added/deleted in this change. Code changes to Linux kernel are as follows.

 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 fed46dd..06058c4 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);
 }

Leave a Reply

Your email address will not be published. Required fields are marked *