arm64, kfence: enable KFENCE for ARM64 39/281539/1
authorMarco Elver <elver@google.com>
Tue, 3 Nov 2020 17:58:35 +0000 (18:58 +0100)
committerSeung-Woo Kim <sw0312.kim@samsung.com>
Tue, 20 Sep 2022 02:42:12 +0000 (11:42 +0900)
Add architecture specific implementation details for KFENCE and enable
KFENCE for the arm64 architecture. In particular, this implements the
required interface in <asm/kfence.h>.

KFENCE requires that attributes for pages from its memory pool can
individually be set. Therefore, force the entire linear map to be mapped
at page granularity. Doing so may result in extra memory allocated for
page tables in case rodata=full is not set; however, currently
CONFIG_RODATA_FULL_DEFAULT_ENABLED=y is the default, and the common case
is therefore not affected by this change.

Reviewed-by: Dmitry Vyukov <dvyukov@google.com>
Co-developed-by: Alexander Potapenko <glider@google.com>
Signed-off-by: Alexander Potapenko <glider@google.com>
Signed-off-by: Marco Elver <elver@google.com>
Reviewed-by: Jann Horn <jannh@google.com>
Reviewed-by: Mark Rutland <mark.rutland@arm.com>
[port kfence feature to rpi-5.10.95]
Signed-off-by: Sung-hun Kim <sfoon.kim@samsung.com>
Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
Signed-off-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Change-Id: I1cb00f8faea0324b850f4c5879a51b1721bc155f

arch/arm64/Kconfig
arch/arm64/include/asm/kfence.h [new file with mode: 0644]
arch/arm64/mm/fault.c
arch/arm64/mm/mmu.c

index 3ba7b56..29874f2 100644 (file)
@@ -137,6 +137,7 @@ config ARM64
        select HAVE_ARCH_JUMP_LABEL_RELATIVE
        select HAVE_ARCH_KASAN if !(ARM64_16K_PAGES && ARM64_VA_BITS_48)
        select HAVE_ARCH_KASAN_SW_TAGS if HAVE_ARCH_KASAN
+       select HAVE_ARCH_KFENCE
        select HAVE_ARCH_KGDB
        select HAVE_ARCH_MMAP_RND_BITS
        select HAVE_ARCH_MMAP_RND_COMPAT_BITS if COMPAT
diff --git a/arch/arm64/include/asm/kfence.h b/arch/arm64/include/asm/kfence.h
new file mode 100644 (file)
index 0000000..5ac0f59
--- /dev/null
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef __ASM_KFENCE_H
+#define __ASM_KFENCE_H
+
+#include <asm/cacheflush.h>
+
+#define KFENCE_SKIP_ARCH_FAULT_HANDLER "el1_sync"
+
+static inline bool arch_kfence_init_pool(void) { return true; }
+
+static inline bool kfence_protect_page(unsigned long addr, bool protect)
+{
+       set_memory_valid(addr, 1, !protect);
+
+       return true;
+}
+
+#endif /* __ASM_KFENCE_H */
index 795d224..d1a8b52 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/acpi.h>
 #include <linux/bitfield.h>
 #include <linux/extable.h>
+#include <linux/kfence.h>
 #include <linux/signal.h>
 #include <linux/mm.h>
 #include <linux/hardirq.h>
@@ -322,6 +323,9 @@ static void __do_kernel_fault(unsigned long addr, unsigned int esr,
        } else if (addr < PAGE_SIZE) {
                msg = "NULL pointer dereference";
        } else {
+               if (kfence_handle_page_fault(addr))
+                       return;
+
                msg = "paging request";
        }
 
index c68e444..22098c5 100644 (file)
@@ -1493,8 +1493,12 @@ int arch_add_memory(int nid, u64 start, u64 size,
 {
        int ret, flags = 0;
 
-       VM_BUG_ON(!mhp_range_allowed(start, size, true));
-       if (rodata_full || debug_pagealloc_enabled())
+       /*
+        * KFENCE requires linear map to be mapped at page granularity, so that
+        * it is possible to protect/unprotect single pages in the KFENCE pool.
+        */
+       if (rodata_full || debug_pagealloc_enabled() ||
+           IS_ENABLED(CONFIG_KFENCE))
                flags = NO_BLOCK_MAPPINGS | NO_CONT_MAPPINGS;
 
        __create_pgd_mapping(swapper_pg_dir, start, __phys_to_virt(start),