]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
kernel: VirtBox workaround for dynamically allocated text
authorMike Kravetz <mike.kravetz@oracle.com>
Wed, 16 Dec 2015 18:26:40 +0000 (10:26 -0800)
committerChuck Anderson <chuck.anderson@oracle.com>
Fri, 26 Feb 2016 03:04:47 +0000 (19:04 -0800)
Orabug: 22377612

VirtualBox dynamically allocates space for executable text within the
kernel.  When these text addresses are encountered by stack trace back
code, they are dropped or the stack trace is terminated.

Ideally, an interface would be created so that routines could registered
to validate kernel text addresses.  Drivers like VirtualBox, would register
routines which know about dynamically allocated text.  However, this will
need more use cases from code in the mainline linux tree.

As a workaround, assume executable pages in vmalloc or module areas are
valid text addresses.  The #ifdef CONFIG_X86 is acceptable as VirtualBox
only supports x86 architecture.

Signed-off-by: Mike Kravetz <mike.kravetz@oracle.com>
kernel/extable.c

index c98f926277a8de676335eba7507eebc0513e93a9..c0367cd4014e201ed40de8a962fc3bd356f8c765 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/ftrace.h>
 #include <linux/mutex.h>
 #include <linux/init.h>
+#include <linux/mm.h>
 
 #include <asm/sections.h>
 #include <asm/uaccess.h>
@@ -59,6 +60,36 @@ const struct exception_table_entry *search_exception_tables(unsigned long addr)
        return e;
 }
 
+/*
+ * VirtualBox dynamically adds kernel executable code to the module
+ * and vmalloc areas.  As a UEK specific workaround, look for pages
+ * in these areas that are executable.  The longer term solution is
+ * to have VirtualBox register a routine to validate kernel executable
+ * code it adds.  However, this will need more use cases from kernel
+ * code in the mainline linux tree.
+ */
+static inline int vmalloc_or_module_exec_page(unsigned long vaddr)
+{
+       int ret = 0;
+
+#ifdef CONFIG_X86
+       /*
+        * The following code (lookup_address) is not available on
+        * all architectures.  This is only needed on x86, as this
+        * is the only architecture supported by VirtualBox.
+        */
+       if (is_vmalloc_or_module_addr((void *)vaddr)) {
+               unsigned int level;
+               pte_t *pte = lookup_address(vaddr, &level);
+
+               if (pte && pte_present(*pte) && pte_exec(*pte))
+                       ret = 1;
+       }
+#endif
+
+       return ret;
+}
+
 static inline int init_kernel_text(unsigned long addr)
 {
        if (addr >= (unsigned long)_sinittext &&
@@ -115,6 +146,13 @@ int __kernel_text_address(unsigned long addr)
         */
        if (init_kernel_text(addr))
                return 1;
+
+       /*
+        * UEK specific workaround for VirtualBox
+        */
+       if (vmalloc_or_module_exec_page(addr))
+               return 1;
+
        return 0;
 }
 
@@ -124,7 +162,12 @@ int kernel_text_address(unsigned long addr)
                return 1;
        if (is_module_text_address(addr))
                return 1;
-       return is_ftrace_trampoline(addr);
+       if (is_ftrace_trampoline(addr))
+               return 1;
+       /*
+        * UEK specific workaround for VirtualBox
+        */
+       return vmalloc_or_module_exec_page(addr);
 }
 
 /*