mm: vmalloc: pass additional vm_flags to __vmalloc_node_range()
authorAndrey Ryabinin <a.ryabinin@samsung.com>
Fri, 13 Feb 2015 22:40:07 +0000 (14:40 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 14 Feb 2015 05:21:42 +0000 (21:21 -0800)
For instrumenting global variables KASan will shadow memory backing memory
for modules.  So on module loading we will need to allocate memory for
shadow and map it at address in shadow that corresponds to the address
allocated in module_alloc().

__vmalloc_node_range() could be used for this purpose, except it puts a
guard hole after allocated area.  Guard hole in shadow memory should be a
problem because at some future point we might need to have a shadow memory
at address occupied by guard hole.  So we could fail to allocate shadow
for module_alloc().

Now we have VM_NO_GUARD flag disabling guard page, so we need to pass into
__vmalloc_node_range().  Add new parameter 'vm_flags' to
__vmalloc_node_range() function.

Signed-off-by: Andrey Ryabinin <a.ryabinin@samsung.com>
Cc: Dmitry Vyukov <dvyukov@google.com>
Cc: Konstantin Serebryany <kcc@google.com>
Cc: Dmitry Chernenkov <dmitryc@google.com>
Signed-off-by: Andrey Konovalov <adech.fo@gmail.com>
Cc: Yuri Gribov <tetra2005@gmail.com>
Cc: Konstantin Khlebnikov <koct9i@gmail.com>
Cc: Sasha Levin <sasha.levin@oracle.com>
Cc: Christoph Lameter <cl@linux.com>
Cc: Joonsoo Kim <iamjoonsoo.kim@lge.com>
Cc: Dave Hansen <dave.hansen@intel.com>
Cc: Andi Kleen <andi@firstfloor.org>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: Christoph Lameter <cl@linux.com>
Cc: Pekka Enberg <penberg@kernel.org>
Cc: David Rientjes <rientjes@google.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
arch/arm/kernel/module.c
arch/arm64/kernel/module.c
arch/mips/kernel/module.c
arch/parisc/kernel/module.c
arch/s390/kernel/module.c
arch/sparc/kernel/module.c
arch/unicore32/kernel/module.c
arch/x86/kernel/module.c
include/linux/vmalloc.h
mm/vmalloc.c

index bea7db9e5b80935a2b164922ea62b5b55c77c01c..2e11961f65ae0a005d53a22c45753879c7b6c904 100644 (file)
@@ -41,7 +41,7 @@
 void *module_alloc(unsigned long size)
 {
        return __vmalloc_node_range(size, 1, MODULES_VADDR, MODULES_END,
-                               GFP_KERNEL, PAGE_KERNEL_EXEC, NUMA_NO_NODE,
+                               GFP_KERNEL, PAGE_KERNEL_EXEC, 0, NUMA_NO_NODE,
                                __builtin_return_address(0));
 }
 #endif
index 9b6f71db270952ad72cbfb30c767fcf2320092f9..67bf4107f6efe8401e1df29ad471ff8aac8cb01d 100644 (file)
@@ -35,8 +35,8 @@
 void *module_alloc(unsigned long size)
 {
        return __vmalloc_node_range(size, 1, MODULES_VADDR, MODULES_END,
-                                   GFP_KERNEL, PAGE_KERNEL_EXEC, NUMA_NO_NODE,
-                                   __builtin_return_address(0));
+                                   GFP_KERNEL, PAGE_KERNEL_EXEC, 0,
+                                   NUMA_NO_NODE, __builtin_return_address(0));
 }
 
 enum aarch64_reloc_op {
index 2a52568dbcd6786cf0ca3c7100f056abba8ed08b..1833f5171ccda092a74f6ac6a902d30e397fc985 100644 (file)
@@ -47,7 +47,7 @@ static DEFINE_SPINLOCK(dbe_lock);
 void *module_alloc(unsigned long size)
 {
        return __vmalloc_node_range(size, 1, MODULE_START, MODULE_END,
-                               GFP_KERNEL, PAGE_KERNEL, NUMA_NO_NODE,
+                               GFP_KERNEL, PAGE_KERNEL, 0, NUMA_NO_NODE,
                                __builtin_return_address(0));
 }
 #endif
index 5822e8e200e6be1ab110b15baf94d4581624099c..3c63a820fcda410544a425f7a2debadca093a8e2 100644 (file)
@@ -219,7 +219,7 @@ void *module_alloc(unsigned long size)
         * init_data correctly */
        return __vmalloc_node_range(size, 1, VMALLOC_START, VMALLOC_END,
                                    GFP_KERNEL | __GFP_HIGHMEM,
-                                   PAGE_KERNEL_RWX, NUMA_NO_NODE,
+                                   PAGE_KERNEL_RWX, 0, NUMA_NO_NODE,
                                    __builtin_return_address(0));
 }
 
index 409d152585bea67a6aca845bb0c3e4db130b1505..36154a2f1814f71a036b68713eeaaf9b1bea7f1f 100644 (file)
@@ -50,7 +50,7 @@ void *module_alloc(unsigned long size)
        if (PAGE_ALIGN(size) > MODULES_LEN)
                return NULL;
        return __vmalloc_node_range(size, 1, MODULES_VADDR, MODULES_END,
-                                   GFP_KERNEL, PAGE_KERNEL, NUMA_NO_NODE,
+                                   GFP_KERNEL, PAGE_KERNEL, 0, NUMA_NO_NODE,
                                    __builtin_return_address(0));
 }
 #endif
index 97655e0fd2438cdee8188bb4748a3c1c87f825fa..192a617a32f3cfd192cd76b484e3cc853e58cba2 100644 (file)
@@ -29,7 +29,7 @@ static void *module_map(unsigned long size)
        if (PAGE_ALIGN(size) > MODULES_LEN)
                return NULL;
        return __vmalloc_node_range(size, 1, MODULES_VADDR, MODULES_END,
-                               GFP_KERNEL, PAGE_KERNEL, NUMA_NO_NODE,
+                               GFP_KERNEL, PAGE_KERNEL, 0, NUMA_NO_NODE,
                                __builtin_return_address(0));
 }
 #else
index dc41f6dfedb6faad50e5b2dfc597aa2f19d208c7..e191b3448bd3015c7caac1c5cc9ce07cd0db1991 100644 (file)
@@ -25,7 +25,7 @@
 void *module_alloc(unsigned long size)
 {
        return __vmalloc_node_range(size, 1, MODULES_VADDR, MODULES_END,
-                               GFP_KERNEL, PAGE_KERNEL_EXEC, NUMA_NO_NODE,
+                               GFP_KERNEL, PAGE_KERNEL_EXEC, 0, NUMA_NO_NODE,
                                __builtin_return_address(0));
 }
 
index e69f9882bf95a942ae1ce0f75efbf07301c9adc3..e830e61aae059309a3a16ef0b30a08b5c56e1ca4 100644 (file)
@@ -88,7 +88,7 @@ void *module_alloc(unsigned long size)
        return __vmalloc_node_range(size, 1,
                                    MODULES_VADDR + get_module_load_offset(),
                                    MODULES_END, GFP_KERNEL | __GFP_HIGHMEM,
-                                   PAGE_KERNEL_EXEC, NUMA_NO_NODE,
+                                   PAGE_KERNEL_EXEC, 0, NUMA_NO_NODE,
                                    __builtin_return_address(0));
 }
 
index 1526fe712ca0368e73e0c0659b65baec7a4ddf42..7d7acb35603d6d6e4bb8a468fcb635d666fea001 100644 (file)
@@ -76,7 +76,9 @@ extern void *vmalloc_32_user(unsigned long size);
 extern void *__vmalloc(unsigned long size, gfp_t gfp_mask, pgprot_t prot);
 extern void *__vmalloc_node_range(unsigned long size, unsigned long align,
                        unsigned long start, unsigned long end, gfp_t gfp_mask,
-                       pgprot_t prot, int node, const void *caller);
+                       pgprot_t prot, unsigned long vm_flags, int node,
+                       const void *caller);
+
 extern void vfree(const void *addr);
 
 extern void *vmap(struct page **pages, unsigned int count,
index 2e74e99d4cfe84e7287e828d2ba4950651e08e37..35b25e1340ca49cf0a95bbc80c69490ec68b5554 100644 (file)
@@ -1619,6 +1619,7 @@ fail:
  *     @end:           vm area range end
  *     @gfp_mask:      flags for the page level allocator
  *     @prot:          protection mask for the allocated pages
+ *     @vm_flags:      additional vm area flags (e.g. %VM_NO_GUARD)
  *     @node:          node to use for allocation or NUMA_NO_NODE
  *     @caller:        caller's return address
  *
@@ -1628,7 +1629,8 @@ fail:
  */
 void *__vmalloc_node_range(unsigned long size, unsigned long align,
                        unsigned long start, unsigned long end, gfp_t gfp_mask,
-                       pgprot_t prot, int node, const void *caller)
+                       pgprot_t prot, unsigned long vm_flags, int node,
+                       const void *caller)
 {
        struct vm_struct *area;
        void *addr;
@@ -1638,8 +1640,8 @@ void *__vmalloc_node_range(unsigned long size, unsigned long align,
        if (!size || (size >> PAGE_SHIFT) > totalram_pages)
                goto fail;
 
-       area = __get_vm_area_node(size, align, VM_ALLOC | VM_UNINITIALIZED,
-                                 start, end, node, gfp_mask, caller);
+       area = __get_vm_area_node(size, align, VM_ALLOC | VM_UNINITIALIZED |
+                               vm_flags, start, end, node, gfp_mask, caller);
        if (!area)
                goto fail;
 
@@ -1688,7 +1690,7 @@ static void *__vmalloc_node(unsigned long size, unsigned long align,
                            int node, const void *caller)
 {
        return __vmalloc_node_range(size, align, VMALLOC_START, VMALLOC_END,
-                               gfp_mask, prot, node, caller);
+                               gfp_mask, prot, 0, node, caller);
 }
 
 void *__vmalloc(unsigned long size, gfp_t gfp_mask, pgprot_t prot)