|
|
|
@ -1,368 +0,0 @@
|
|
|
|
|
From 0a4b63f55fec9c1c505c5429afbc1e512df2415e Mon Sep 17 00:00:00 2001
|
|
|
|
|
From: Fedora Kernel Team <kernel-team@fedoraproject.org>
|
|
|
|
|
Date: Wed, 11 Dec 2019 11:55:51 +0000
|
|
|
|
|
Subject: [PATCH] RISCV KASAN
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
Documentation/dev-tools/kasan.rst | 4 +-
|
|
|
|
|
arch/riscv/Kconfig | 1 +
|
|
|
|
|
arch/riscv/include/asm/kasan.h | 27 ++++++++
|
|
|
|
|
arch/riscv/include/asm/pgtable-64.h | 5 ++
|
|
|
|
|
arch/riscv/include/asm/string.h | 9 +++
|
|
|
|
|
arch/riscv/kernel/head.S | 3 +
|
|
|
|
|
arch/riscv/kernel/riscv_ksyms.c | 2 +
|
|
|
|
|
arch/riscv/kernel/setup.c | 5 ++
|
|
|
|
|
arch/riscv/kernel/vmlinux.lds.S | 1 +
|
|
|
|
|
arch/riscv/lib/memcpy.S | 5 +-
|
|
|
|
|
arch/riscv/lib/memset.S | 5 +-
|
|
|
|
|
arch/riscv/mm/Makefile | 6 ++
|
|
|
|
|
arch/riscv/mm/kasan_init.c | 104 ++++++++++++++++++++++++++++
|
|
|
|
|
mm/kasan/common.c | 2 +
|
|
|
|
|
14 files changed, 173 insertions(+), 6 deletions(-)
|
|
|
|
|
create mode 100644 arch/riscv/include/asm/kasan.h
|
|
|
|
|
create mode 100644 arch/riscv/mm/kasan_init.c
|
|
|
|
|
|
|
|
|
|
diff --git a/Documentation/dev-tools/kasan.rst b/Documentation/dev-tools/kasan.rst
|
|
|
|
|
index 5252961..a97f5b0 100644
|
|
|
|
|
--- a/Documentation/dev-tools/kasan.rst
|
|
|
|
|
+++ b/Documentation/dev-tools/kasan.rst
|
|
|
|
|
@@ -21,8 +21,8 @@ global variables yet.
|
|
|
|
|
|
|
|
|
|
Tag-based KASAN is only supported in Clang and requires version 7.0.0 or later.
|
|
|
|
|
|
|
|
|
|
-Currently generic KASAN is supported for the x86_64, arm64, xtensa and s390
|
|
|
|
|
-architectures, and tag-based KASAN is supported only for arm64.
|
|
|
|
|
+Currently generic KASAN is supported for the x86_64, arm64, xtensa, s390 and
|
|
|
|
|
+riscv architectures, and tag-based KASAN is supported only for arm64.
|
|
|
|
|
|
|
|
|
|
Usage
|
|
|
|
|
-----
|
|
|
|
|
diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
|
|
|
|
|
index 8eebbc8..ca2fc8b 100644
|
|
|
|
|
--- a/arch/riscv/Kconfig
|
|
|
|
|
+++ b/arch/riscv/Kconfig
|
|
|
|
|
@@ -61,6 +61,7 @@ config RISCV
|
|
|
|
|
select SPARSEMEM_STATIC if 32BIT
|
|
|
|
|
select ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT if MMU
|
|
|
|
|
select HAVE_ARCH_MMAP_RND_BITS
|
|
|
|
|
+ select HAVE_ARCH_KASAN if MMU && 64BIT
|
|
|
|
|
|
|
|
|
|
config ARCH_MMAP_RND_BITS_MIN
|
|
|
|
|
default 18 if 64BIT
|
|
|
|
|
diff --git a/arch/riscv/include/asm/kasan.h b/arch/riscv/include/asm/kasan.h
|
|
|
|
|
new file mode 100644
|
|
|
|
|
index 0000000..eee6e65
|
|
|
|
|
--- /dev/null
|
|
|
|
|
+++ b/arch/riscv/include/asm/kasan.h
|
|
|
|
|
@@ -0,0 +1,27 @@
|
|
|
|
|
+/* SPDX-License-Identifier: GPL-2.0 */
|
|
|
|
|
+/* Copyright (C) 2019 Andes Technology Corporation */
|
|
|
|
|
+
|
|
|
|
|
+#ifndef __ASM_KASAN_H
|
|
|
|
|
+#define __ASM_KASAN_H
|
|
|
|
|
+
|
|
|
|
|
+#ifndef __ASSEMBLY__
|
|
|
|
|
+
|
|
|
|
|
+#ifdef CONFIG_KASAN
|
|
|
|
|
+
|
|
|
|
|
+#include <asm/pgtable.h>
|
|
|
|
|
+
|
|
|
|
|
+#define KASAN_SHADOW_SCALE_SHIFT 3
|
|
|
|
|
+
|
|
|
|
|
+#define KASAN_SHADOW_SIZE (UL(1) << (38 - KASAN_SHADOW_SCALE_SHIFT))
|
|
|
|
|
+#define KASAN_SHADOW_START 0xffffffc000000000 /* 2^64 - 2^38 */
|
|
|
|
|
+#define KASAN_SHADOW_END (KASAN_SHADOW_START + KASAN_SHADOW_SIZE)
|
|
|
|
|
+
|
|
|
|
|
+#define KASAN_SHADOW_OFFSET (KASAN_SHADOW_END - (1ULL << \
|
|
|
|
|
+ (64 - KASAN_SHADOW_SCALE_SHIFT)))
|
|
|
|
|
+
|
|
|
|
|
+void kasan_init(void);
|
|
|
|
|
+asmlinkage void kasan_early_init(void);
|
|
|
|
|
+
|
|
|
|
|
+#endif
|
|
|
|
|
+#endif
|
|
|
|
|
+#endif /* __ASM_KASAN_H */
|
|
|
|
|
diff --git a/arch/riscv/include/asm/pgtable-64.h b/arch/riscv/include/asm/pgtable-64.h
|
|
|
|
|
index 7463098..36e638d 100644
|
|
|
|
|
--- a/arch/riscv/include/asm/pgtable-64.h
|
|
|
|
|
+++ b/arch/riscv/include/asm/pgtable-64.h
|
|
|
|
|
@@ -58,6 +58,11 @@ static inline unsigned long pud_page_vaddr(pud_t pud)
|
|
|
|
|
return (unsigned long)pfn_to_virt(pud_val(pud) >> _PAGE_PFN_SHIFT);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
+static inline struct page *pud_page(pud_t pud)
|
|
|
|
|
+{
|
|
|
|
|
+ return pfn_to_page(pud_val(pud) >> _PAGE_PFN_SHIFT);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
#define pmd_index(addr) (((addr) >> PMD_SHIFT) & (PTRS_PER_PMD - 1))
|
|
|
|
|
|
|
|
|
|
static inline pmd_t *pmd_offset(pud_t *pud, unsigned long addr)
|
|
|
|
|
diff --git a/arch/riscv/include/asm/string.h b/arch/riscv/include/asm/string.h
|
|
|
|
|
index 1b5d445..924af13 100644
|
|
|
|
|
--- a/arch/riscv/include/asm/string.h
|
|
|
|
|
+++ b/arch/riscv/include/asm/string.h
|
|
|
|
|
@@ -11,8 +11,17 @@
|
|
|
|
|
|
|
|
|
|
#define __HAVE_ARCH_MEMSET
|
|
|
|
|
extern asmlinkage void *memset(void *, int, size_t);
|
|
|
|
|
+extern asmlinkage void *__memset(void *, int, size_t);
|
|
|
|
|
|
|
|
|
|
#define __HAVE_ARCH_MEMCPY
|
|
|
|
|
extern asmlinkage void *memcpy(void *, const void *, size_t);
|
|
|
|
|
+extern asmlinkage void *__memcpy(void *, const void *, size_t);
|
|
|
|
|
|
|
|
|
|
+/* For those files which don't want to check by kasan. */
|
|
|
|
|
+#if defined(CONFIG_KASAN) && !defined(__SANITIZE_ADDRESS__)
|
|
|
|
|
+
|
|
|
|
|
+#define memcpy(dst, src, len) __memcpy(dst, src, len)
|
|
|
|
|
+#define memset(s, c, n) __memset(s, c, n)
|
|
|
|
|
+
|
|
|
|
|
+#endif
|
|
|
|
|
#endif /* _ASM_RISCV_STRING_H */
|
|
|
|
|
diff --git a/arch/riscv/kernel/head.S b/arch/riscv/kernel/head.S
|
|
|
|
|
index 72f89b7..95eca23 100644
|
|
|
|
|
--- a/arch/riscv/kernel/head.S
|
|
|
|
|
+++ b/arch/riscv/kernel/head.S
|
|
|
|
|
@@ -102,6 +102,9 @@ clear_bss_done:
|
|
|
|
|
sw zero, TASK_TI_CPU(tp)
|
|
|
|
|
la sp, init_thread_union + THREAD_SIZE
|
|
|
|
|
|
|
|
|
|
+#ifdef CONFIG_KASAN
|
|
|
|
|
+ call kasan_early_init
|
|
|
|
|
+#endif
|
|
|
|
|
/* Start the kernel */
|
|
|
|
|
call parse_dtb
|
|
|
|
|
tail start_kernel
|
|
|
|
|
diff --git a/arch/riscv/kernel/riscv_ksyms.c b/arch/riscv/kernel/riscv_ksyms.c
|
|
|
|
|
index 4800cf7..376bba7 100644
|
|
|
|
|
--- a/arch/riscv/kernel/riscv_ksyms.c
|
|
|
|
|
+++ b/arch/riscv/kernel/riscv_ksyms.c
|
|
|
|
|
@@ -14,3 +14,5 @@ EXPORT_SYMBOL(__asm_copy_to_user);
|
|
|
|
|
EXPORT_SYMBOL(__asm_copy_from_user);
|
|
|
|
|
EXPORT_SYMBOL(memset);
|
|
|
|
|
EXPORT_SYMBOL(memcpy);
|
|
|
|
|
+EXPORT_SYMBOL(__memset);
|
|
|
|
|
+EXPORT_SYMBOL(__memcpy);
|
|
|
|
|
diff --git a/arch/riscv/kernel/setup.c b/arch/riscv/kernel/setup.c
|
|
|
|
|
index 845ae0e..cfb833a 100644
|
|
|
|
|
--- a/arch/riscv/kernel/setup.c
|
|
|
|
|
+++ b/arch/riscv/kernel/setup.c
|
|
|
|
|
@@ -23,6 +23,7 @@
|
|
|
|
|
#include <asm/smp.h>
|
|
|
|
|
#include <asm/tlbflush.h>
|
|
|
|
|
#include <asm/thread_info.h>
|
|
|
|
|
+#include <asm/kasan.h>
|
|
|
|
|
|
|
|
|
|
#include "head.h"
|
|
|
|
|
|
|
|
|
|
@@ -72,6 +73,10 @@ void __init setup_arch(char **cmdline_p)
|
|
|
|
|
swiotlb_init(1);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
+#ifdef CONFIG_KASAN
|
|
|
|
|
+ kasan_init();
|
|
|
|
|
+#endif
|
|
|
|
|
+
|
|
|
|
|
#ifdef CONFIG_SMP
|
|
|
|
|
setup_smp();
|
|
|
|
|
#endif
|
|
|
|
|
diff --git a/arch/riscv/kernel/vmlinux.lds.S b/arch/riscv/kernel/vmlinux.lds.S
|
|
|
|
|
index 23cd1a9..9700980 100644
|
|
|
|
|
--- a/arch/riscv/kernel/vmlinux.lds.S
|
|
|
|
|
+++ b/arch/riscv/kernel/vmlinux.lds.S
|
|
|
|
|
@@ -46,6 +46,7 @@ SECTIONS
|
|
|
|
|
KPROBES_TEXT
|
|
|
|
|
ENTRY_TEXT
|
|
|
|
|
IRQENTRY_TEXT
|
|
|
|
|
+ SOFTIRQENTRY_TEXT
|
|
|
|
|
*(.fixup)
|
|
|
|
|
_etext = .;
|
|
|
|
|
}
|
|
|
|
|
diff --git a/arch/riscv/lib/memcpy.S b/arch/riscv/lib/memcpy.S
|
|
|
|
|
index b4c4778..51ab716 100644
|
|
|
|
|
--- a/arch/riscv/lib/memcpy.S
|
|
|
|
|
+++ b/arch/riscv/lib/memcpy.S
|
|
|
|
|
@@ -7,7 +7,8 @@
|
|
|
|
|
#include <asm/asm.h>
|
|
|
|
|
|
|
|
|
|
/* void *memcpy(void *, const void *, size_t) */
|
|
|
|
|
-ENTRY(memcpy)
|
|
|
|
|
+ENTRY(__memcpy)
|
|
|
|
|
+WEAK(memcpy)
|
|
|
|
|
move t6, a0 /* Preserve return value */
|
|
|
|
|
|
|
|
|
|
/* Defer to byte-oriented copy for small sizes */
|
|
|
|
|
@@ -104,4 +105,4 @@ ENTRY(memcpy)
|
|
|
|
|
bltu a1, a3, 5b
|
|
|
|
|
6:
|
|
|
|
|
ret
|
|
|
|
|
-END(memcpy)
|
|
|
|
|
+END(__memcpy)
|
|
|
|
|
diff --git a/arch/riscv/lib/memset.S b/arch/riscv/lib/memset.S
|
|
|
|
|
index 5a7386b..34c5360 100644
|
|
|
|
|
--- a/arch/riscv/lib/memset.S
|
|
|
|
|
+++ b/arch/riscv/lib/memset.S
|
|
|
|
|
@@ -8,7 +8,8 @@
|
|
|
|
|
#include <asm/asm.h>
|
|
|
|
|
|
|
|
|
|
/* void *memset(void *, int, size_t) */
|
|
|
|
|
-ENTRY(memset)
|
|
|
|
|
+ENTRY(__memset)
|
|
|
|
|
+WEAK(memset)
|
|
|
|
|
move t0, a0 /* Preserve return value */
|
|
|
|
|
|
|
|
|
|
/* Defer to byte-oriented fill for small sizes */
|
|
|
|
|
@@ -109,4 +110,4 @@ ENTRY(memset)
|
|
|
|
|
bltu t0, a3, 5b
|
|
|
|
|
6:
|
|
|
|
|
ret
|
|
|
|
|
-END(memset)
|
|
|
|
|
+END(__memset)
|
|
|
|
|
diff --git a/arch/riscv/mm/Makefile b/arch/riscv/mm/Makefile
|
|
|
|
|
index 9d9a173..b8a8ca7 100644
|
|
|
|
|
--- a/arch/riscv/mm/Makefile
|
|
|
|
|
+++ b/arch/riscv/mm/Makefile
|
|
|
|
|
@@ -17,3 +17,9 @@ ifeq ($(CONFIG_MMU),y)
|
|
|
|
|
obj-$(CONFIG_SMP) += tlbflush.o
|
|
|
|
|
endif
|
|
|
|
|
obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
|
|
|
|
|
+obj-$(CONFIG_KASAN) += kasan_init.o
|
|
|
|
|
+
|
|
|
|
|
+ifdef CONFIG_KASAN
|
|
|
|
|
+KASAN_SANITIZE_kasan_init.o := n
|
|
|
|
|
+KASAN_SANITIZE_init.o := n
|
|
|
|
|
+endif
|
|
|
|
|
diff --git a/arch/riscv/mm/kasan_init.c b/arch/riscv/mm/kasan_init.c
|
|
|
|
|
new file mode 100644
|
|
|
|
|
index 0000000..f0cc860
|
|
|
|
|
--- /dev/null
|
|
|
|
|
+++ b/arch/riscv/mm/kasan_init.c
|
|
|
|
|
@@ -0,0 +1,104 @@
|
|
|
|
|
+// SPDX-License-Identifier: GPL-2.0
|
|
|
|
|
+// Copyright (C) 2019 Andes Technology Corporation
|
|
|
|
|
+
|
|
|
|
|
+#include <linux/pfn.h>
|
|
|
|
|
+#include <linux/init_task.h>
|
|
|
|
|
+#include <linux/kasan.h>
|
|
|
|
|
+#include <linux/kernel.h>
|
|
|
|
|
+#include <linux/memblock.h>
|
|
|
|
|
+#include <asm/tlbflush.h>
|
|
|
|
|
+#include <asm/pgtable.h>
|
|
|
|
|
+#include <asm/fixmap.h>
|
|
|
|
|
+
|
|
|
|
|
+extern pgd_t early_pg_dir[PTRS_PER_PGD];
|
|
|
|
|
+asmlinkage void __init kasan_early_init(void)
|
|
|
|
|
+{
|
|
|
|
|
+ uintptr_t i;
|
|
|
|
|
+ pgd_t *pgd = early_pg_dir + pgd_index(KASAN_SHADOW_START);
|
|
|
|
|
+
|
|
|
|
|
+ for (i = 0; i < PTRS_PER_PTE; ++i)
|
|
|
|
|
+ set_pte(kasan_early_shadow_pte + i,
|
|
|
|
|
+ mk_pte(virt_to_page(kasan_early_shadow_page),
|
|
|
|
|
+ PAGE_KERNEL));
|
|
|
|
|
+
|
|
|
|
|
+ for (i = 0; i < PTRS_PER_PMD; ++i)
|
|
|
|
|
+ set_pmd(kasan_early_shadow_pmd + i,
|
|
|
|
|
+ pfn_pmd(PFN_DOWN(__pa((uintptr_t)kasan_early_shadow_pte)),
|
|
|
|
|
+ __pgprot(_PAGE_TABLE)));
|
|
|
|
|
+
|
|
|
|
|
+ for (i = KASAN_SHADOW_START; i < KASAN_SHADOW_END;
|
|
|
|
|
+ i += PGDIR_SIZE, ++pgd)
|
|
|
|
|
+ set_pgd(pgd,
|
|
|
|
|
+ pfn_pgd(PFN_DOWN(__pa(((uintptr_t)kasan_early_shadow_pmd))),
|
|
|
|
|
+ __pgprot(_PAGE_TABLE)));
|
|
|
|
|
+
|
|
|
|
|
+ /* init for swapper_pg_dir */
|
|
|
|
|
+ pgd = pgd_offset_k(KASAN_SHADOW_START);
|
|
|
|
|
+
|
|
|
|
|
+ for (i = KASAN_SHADOW_START; i < KASAN_SHADOW_END;
|
|
|
|
|
+ i += PGDIR_SIZE, ++pgd)
|
|
|
|
|
+ set_pgd(pgd,
|
|
|
|
|
+ pfn_pgd(PFN_DOWN(__pa(((uintptr_t)kasan_early_shadow_pmd))),
|
|
|
|
|
+ __pgprot(_PAGE_TABLE)));
|
|
|
|
|
+
|
|
|
|
|
+ flush_tlb_all();
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+static void __init populate(void *start, void *end)
|
|
|
|
|
+{
|
|
|
|
|
+ unsigned long i;
|
|
|
|
|
+ unsigned long vaddr = (unsigned long)start & PAGE_MASK;
|
|
|
|
|
+ unsigned long vend = PAGE_ALIGN((unsigned long)end);
|
|
|
|
|
+ unsigned long n_pages = (vend - vaddr) / PAGE_SIZE;
|
|
|
|
|
+ unsigned long n_pmds =
|
|
|
|
|
+ (n_pages % PTRS_PER_PTE) ? n_pages / PTRS_PER_PTE + 1 :
|
|
|
|
|
+ n_pages / PTRS_PER_PTE;
|
|
|
|
|
+ pgd_t *pgd = pgd_offset_k(vaddr);
|
|
|
|
|
+ pmd_t *pmd = memblock_alloc(n_pmds * sizeof(pmd_t), PAGE_SIZE);
|
|
|
|
|
+ pte_t *pte = memblock_alloc(n_pages * sizeof(pte_t), PAGE_SIZE);
|
|
|
|
|
+
|
|
|
|
|
+ for (i = 0; i < n_pages; i++) {
|
|
|
|
|
+ phys_addr_t phys = memblock_phys_alloc(PAGE_SIZE, PAGE_SIZE);
|
|
|
|
|
+
|
|
|
|
|
+ set_pte(pte + i, pfn_pte(PHYS_PFN(phys), PAGE_KERNEL));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ for (i = 0; i < n_pmds; ++pgd, i += PTRS_PER_PMD)
|
|
|
|
|
+ set_pgd(pgd, pfn_pgd(PFN_DOWN(__pa(((uintptr_t)(pmd + i)))),
|
|
|
|
|
+ __pgprot(_PAGE_TABLE)));
|
|
|
|
|
+
|
|
|
|
|
+ for (i = 0; i < n_pages; ++pmd, i += PTRS_PER_PTE)
|
|
|
|
|
+ set_pmd(pmd, pfn_pmd(PFN_DOWN(__pa((uintptr_t)(pte + i))),
|
|
|
|
|
+ __pgprot(_PAGE_TABLE)));
|
|
|
|
|
+
|
|
|
|
|
+ flush_tlb_all();
|
|
|
|
|
+ memset(start, 0, end - start);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+void __init kasan_init(void)
|
|
|
|
|
+{
|
|
|
|
|
+ struct memblock_region *reg;
|
|
|
|
|
+ unsigned long i;
|
|
|
|
|
+
|
|
|
|
|
+ kasan_populate_early_shadow((void *)KASAN_SHADOW_START,
|
|
|
|
|
+ (void *)kasan_mem_to_shadow((void *)VMALLOC_END));
|
|
|
|
|
+
|
|
|
|
|
+ for_each_memblock(memory, reg) {
|
|
|
|
|
+ void *start = (void *)__va(reg->base);
|
|
|
|
|
+ void *end = (void *)__va(reg->base + reg->size);
|
|
|
|
|
+
|
|
|
|
|
+ if (start >= end)
|
|
|
|
|
+ break;
|
|
|
|
|
+
|
|
|
|
|
+ populate(kasan_mem_to_shadow(start),
|
|
|
|
|
+ kasan_mem_to_shadow(end));
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ for (i = 0; i < PTRS_PER_PTE; i++)
|
|
|
|
|
+ set_pte(&kasan_early_shadow_pte[i],
|
|
|
|
|
+ mk_pte(virt_to_page(kasan_early_shadow_page),
|
|
|
|
|
+ __pgprot(_PAGE_PRESENT | _PAGE_READ | _PAGE_ACCESSED)));
|
|
|
|
|
+
|
|
|
|
|
+ memset(kasan_early_shadow_page, 0, PAGE_SIZE);
|
|
|
|
|
+ init_task.kasan_depth = 0;
|
|
|
|
|
+}
|
|
|
|
|
diff --git a/mm/kasan/common.c b/mm/kasan/common.c
|
|
|
|
|
index 6814d6d..897f952 100644
|
|
|
|
|
--- a/mm/kasan/common.c
|
|
|
|
|
+++ b/mm/kasan/common.c
|
|
|
|
|
@@ -107,6 +107,7 @@ void *memset(void *addr, int c, size_t len)
|
|
|
|
|
return __memset(addr, c, len);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
+#ifdef __HAVE_ARCH_MEMMOVE
|
|
|
|
|
#undef memmove
|
|
|
|
|
void *memmove(void *dest, const void *src, size_t len)
|
|
|
|
|
{
|
|
|
|
|
@@ -115,6 +116,7 @@ void *memmove(void *dest, const void *src, size_t len)
|
|
|
|
|
|
|
|
|
|
return __memmove(dest, src, len);
|
|
|
|
|
}
|
|
|
|
|
+#endif
|
|
|
|
|
|
|
|
|
|
#undef memcpy
|
|
|
|
|
void *memcpy(void *dest, const void *src, size_t len)
|
|
|
|
|
--
|
|
|
|
|
2.24.1
|
|
|
|
|
|