From: Ard Biesheuvel <[email protected]>

Only recent arm64 systems are guaranteed to be able to manipulate the
permissions on live kernel mappings that may use huge mappings. Older
ones can only do so on live mappings that are mapped down to pages.

In order to make execmem caches work on arm64 despite this distinction,
allow huge vmappings to be omitted when allocating the caches.

Signed-off-by: Ard Biesheuvel <[email protected]>
---
 include/linux/execmem.h | 2 ++
 mm/execmem.c            | 3 ++-
 2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/include/linux/execmem.h b/include/linux/execmem.h
index 59bd862cb061..b04926f3fff2 100644
--- a/include/linux/execmem.h
+++ b/include/linux/execmem.h
@@ -48,10 +48,12 @@ enum execmem_type {
  * enum execmem_range_flags - options for executable memory allocations
  * @EXECMEM_KASAN_SHADOW:      allocate kasan shadow
  * @EXECMEM_ROX_CACHE:         allocations should use ROX cache of huge pages
+ * @EXECMEM_NO_HUGE_VMAP:      cache allocations must avoid huge vmappings
  */
 enum execmem_range_flags {
        EXECMEM_KASAN_SHADOW    = (1 << 0),
        EXECMEM_ROX_CACHE       = (1 << 1),
+       EXECMEM_NO_HUGE_VMAP    = (1 << 2),
 };
 
 #ifdef CONFIG_ARCH_HAS_EXECMEM_ROX
diff --git a/mm/execmem.c b/mm/execmem.c
index 6db0c1d82a9d..5790d4a8532a 100644
--- a/mm/execmem.c
+++ b/mm/execmem.c
@@ -276,7 +276,8 @@ static void *__execmem_cache_alloc(struct execmem_range 
*range, size_t size)
 
 static void *execmem_cache_populate_alloc(struct execmem_range *range, size_t 
size)
 {
-       unsigned long vm_flags = VM_ALLOW_HUGE_VMAP;
+       unsigned long vm_flags = (range->flags & EXECMEM_NO_HUGE_VMAP)
+                                               ? 0 : VM_ALLOW_HUGE_VMAP;
        struct mutex *mutex = &execmem_cache.mutex;
        struct vm_struct *vm;
        size_t alloc_size;
-- 
2.55.0.860.g4b6b3295ed-goog


Reply via email to