Add bugfix: arm64/vmalloc: use module region only for module_alloc() if CONFIG_RANDOMIZE_BASE is set Signed-off-by: Zheng Zengkai <zhengzengkai@huawei.com>
115 lines
3.6 KiB
Diff
115 lines
3.6 KiB
Diff
From 986d4fc019dd3cbbc969640fa06a1bd4442b35cf Mon Sep 17 00:00:00 2001
|
|
From: Liu Shixin <liushixin2@huawei.com>
|
|
Date: Mon, 6 Feb 2023 21:35:56 +0800
|
|
Subject: [PATCH] arm64/vmalloc: use module region only for module_alloc() if
|
|
CONFIG_RANDOMIZE_BASE is set
|
|
|
|
hulk inclusion
|
|
category: bugfix
|
|
bugzilla: https://gitee.com/openeuler/kernel/issues/I6DAD6
|
|
|
|
--------------------------------
|
|
|
|
After I add a 10GB pmem device, I got the following error message when
|
|
insert module:
|
|
|
|
insmod: vmalloc error: size 16384, vm_struct allocation failed,
|
|
mode:0xcc0(GFP_KERNEL), nodemask=(null),cpuset=/,mems_allowed=0
|
|
|
|
If CONFIG_RANDOMIZE_BASE is set, the module region can be located in the
|
|
vmalloc region entirely. Although module_alloc() can fall back to a 2GB
|
|
window if ARM64_MODULE_PLTS is set, the module region is still easily
|
|
exhausted because the module region is located at bottom of vmalloc region
|
|
and the vmalloc region is allocated from bottom to top.
|
|
|
|
Skip module region if not calling from module_alloc().
|
|
|
|
Signed-off-by: Liu Shixin <liushixin2@huawei.com>
|
|
Signed-off-by: Zheng Zengkai <zhengzengkai@huawei.com>
|
|
---
|
|
arch/arm64/include/asm/vmalloc.h | 26 ++++++++++++++++++++++++++
|
|
include/linux/vmalloc.h | 9 +++++++++
|
|
mm/vmalloc.c | 4 ++++
|
|
3 files changed, 39 insertions(+)
|
|
|
|
diff --git a/arch/arm64/include/asm/vmalloc.h b/arch/arm64/include/asm/vmalloc.h
|
|
index 38fafffe699f..4feff546b11b 100644
|
|
--- a/arch/arm64/include/asm/vmalloc.h
|
|
+++ b/arch/arm64/include/asm/vmalloc.h
|
|
@@ -31,4 +31,30 @@ static inline pgprot_t arch_vmap_pgprot_tagged(pgprot_t prot)
|
|
return pgprot_tagged(prot);
|
|
}
|
|
|
|
+#ifdef CONFIG_RANDOMIZE_BASE
|
|
+extern u64 module_alloc_base;
|
|
+#define arch_vmap_skip_module_region arch_vmap_skip_module_region
|
|
+static inline void arch_vmap_skip_module_region(unsigned long *addr,
|
|
+ unsigned long vstart,
|
|
+ unsigned long size,
|
|
+ unsigned long align)
|
|
+{
|
|
+ u64 module_alloc_end = module_alloc_base + MODULES_VSIZE;
|
|
+
|
|
+ if (vstart == module_alloc_base)
|
|
+ return;
|
|
+
|
|
+ if (IS_ENABLED(CONFIG_KASAN_GENERIC) ||
|
|
+ IS_ENABLED(CONFIG_KASAN_SW_TAGS))
|
|
+ /* don't exceed the static module region - see module_alloc() */
|
|
+ module_alloc_end = MODULES_END;
|
|
+
|
|
+ if ((module_alloc_base >= *addr + size) ||
|
|
+ (module_alloc_end <= *addr))
|
|
+ return;
|
|
+
|
|
+ *addr = ALIGN(module_alloc_end, align);
|
|
+}
|
|
+#endif
|
|
+
|
|
#endif /* _ASM_ARM64_VMALLOC_H */
|
|
diff --git a/include/linux/vmalloc.h b/include/linux/vmalloc.h
|
|
index 096d48aa3437..55ef97325b84 100644
|
|
--- a/include/linux/vmalloc.h
|
|
+++ b/include/linux/vmalloc.h
|
|
@@ -122,6 +122,15 @@ static inline pgprot_t arch_vmap_pgprot_tagged(pgprot_t prot)
|
|
}
|
|
#endif
|
|
|
|
+#ifndef arch_vmap_skip_module_region
|
|
+static inline void arch_vmap_skip_module_region(unsigned long *addr,
|
|
+ unsigned long vstart,
|
|
+ unsigned long size,
|
|
+ unsigned long align)
|
|
+{
|
|
+}
|
|
+#endif
|
|
+
|
|
/*
|
|
* Highlevel APIs for driver use
|
|
*/
|
|
diff --git a/mm/vmalloc.c b/mm/vmalloc.c
|
|
index ccaa461998f3..929307f8602b 100644
|
|
--- a/mm/vmalloc.c
|
|
+++ b/mm/vmalloc.c
|
|
@@ -1233,6 +1233,8 @@ is_within_this_va(struct vmap_area *va, unsigned long size,
|
|
else
|
|
nva_start_addr = ALIGN(vstart, align);
|
|
|
|
+ arch_vmap_skip_module_region(&nva_start_addr, vstart, size, align);
|
|
+
|
|
/* Can be overflowed due to big size or alignment. */
|
|
if (nva_start_addr + size < nva_start_addr ||
|
|
nva_start_addr < vstart)
|
|
@@ -1520,6 +1522,8 @@ __alloc_vmap_area(struct rb_root *root, struct list_head *head,
|
|
else
|
|
nva_start_addr = ALIGN(vstart, align);
|
|
|
|
+ arch_vmap_skip_module_region(&nva_start_addr, vstart, size, align);
|
|
+
|
|
/* Check the "vend" restriction. */
|
|
if (nva_start_addr + size > vend)
|
|
return vend;
|
|
--
|
|
2.25.1
|
|
|