linux-riscv.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/8] Support strict kernel memory permissions for security
@ 2020-02-17  8:32 Zong Li
  2020-02-17  8:32 ` [PATCH 1/8] riscv: add ARCH_HAS_SET_MEMORY support Zong Li
                   ` (8 more replies)
  0 siblings, 9 replies; 22+ messages in thread
From: Zong Li @ 2020-02-17  8:32 UTC (permalink / raw)
  To: paul.walmsley, palmer, aou, linux-riscv, linux-kernel; +Cc: Zong Li

The main purpose of this patch series is changing the kernel mapping permission
, make sure that code is not writeable, data is not executable, and read-only
data is neither writable nor executable.

This patch series also supports the relevant implementations such as
ARCH_HAS_SET_MEMORY, ARCH_HAS_SET_DIRECT_MAP,
ARCH_SUPPORTS_DEBUG_PAGEALLOC and DEBUG_WX.

Zong Li (8):
  riscv: add ARCH_HAS_SET_MEMORY support
  riscv: add ARCH_HAS_SET_DIRECT_MAP support
  riscv: add ARCH_SUPPORTS_DEBUG_PAGEALLOC support
  riscv: move exception table immediately after RO_DATA
  riscv: add alignment for text, rodata and data sections
  riscv: add STRICT_KERNEL_RWX support
  riscv: add DEBUG_WX support
  riscv: add two hook functions of ftrace

 arch/riscv/Kconfig                  |   6 +
 arch/riscv/Kconfig.debug            |  30 +++++
 arch/riscv/include/asm/ptdump.h     |   6 +
 arch/riscv/include/asm/set_memory.h |  41 ++++++
 arch/riscv/kernel/ftrace.c          |  18 +++
 arch/riscv/kernel/vmlinux.lds.S     |  12 +-
 arch/riscv/mm/Makefile              |   1 +
 arch/riscv/mm/init.c                |  47 +++++++
 arch/riscv/mm/pageattr.c            | 187 ++++++++++++++++++++++++++++
 9 files changed, 344 insertions(+), 4 deletions(-)
 create mode 100644 arch/riscv/include/asm/set_memory.h
 create mode 100644 arch/riscv/mm/pageattr.c

-- 
2.25.0



^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCH 1/8] riscv: add ARCH_HAS_SET_MEMORY support
  2020-02-17  8:32 [PATCH 0/8] Support strict kernel memory permissions for security Zong Li
@ 2020-02-17  8:32 ` Zong Li
  2020-03-05  0:57   ` Palmer Dabbelt
  2020-02-17  8:32 ` [PATCH 2/8] riscv: add ARCH_HAS_SET_DIRECT_MAP support Zong Li
                   ` (7 subsequent siblings)
  8 siblings, 1 reply; 22+ messages in thread
From: Zong Li @ 2020-02-17  8:32 UTC (permalink / raw)
  To: paul.walmsley, palmer, aou, linux-riscv, linux-kernel; +Cc: Zong Li

Add set_memory_ro/rw/x/nx architecture hooks to change the page
attribution.

Use own set_memory.h rather than generic set_memory.h
(i.e. include/asm-generic/set_memory.h), because we want to add other
function prototypes here.

Signed-off-by: Zong Li <zong.li@sifive.com>
---
 arch/riscv/Kconfig                  |   1 +
 arch/riscv/include/asm/set_memory.h |  17 ++++
 arch/riscv/mm/Makefile              |   1 +
 arch/riscv/mm/pageattr.c            | 150 ++++++++++++++++++++++++++++
 4 files changed, 169 insertions(+)
 create mode 100644 arch/riscv/include/asm/set_memory.h
 create mode 100644 arch/riscv/mm/pageattr.c

diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index 6e81da55b5e4..76ed36543b3a 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -60,6 +60,7 @@ config RISCV
 	select HAVE_EBPF_JIT if 64BIT
 	select EDAC_SUPPORT
 	select ARCH_HAS_GIGANTIC_PAGE
+	select ARCH_HAS_SET_MEMORY
 	select ARCH_WANT_HUGE_PMD_SHARE if 64BIT
 	select SPARSEMEM_STATIC if 32BIT
 	select ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT if MMU
diff --git a/arch/riscv/include/asm/set_memory.h b/arch/riscv/include/asm/set_memory.h
new file mode 100644
index 000000000000..936f08063566
--- /dev/null
+++ b/arch/riscv/include/asm/set_memory.h
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) 2019 SiFive
+ */
+
+#ifndef _ASM_RISCV_SET_MEMORY_H
+#define _ASM_RISCV_SET_MEMORY_H
+
+/*
+ * Functions to change memory attributes.
+ */
+int set_memory_ro(unsigned long addr, int numpages);
+int set_memory_rw(unsigned long addr, int numpages);
+int set_memory_x(unsigned long addr, int numpages);
+int set_memory_nx(unsigned long addr, int numpages);
+
+#endif /* _ASM_RISCV_SET_MEMORY_H */
diff --git a/arch/riscv/mm/Makefile b/arch/riscv/mm/Makefile
index 814e16a8d68a..b94643aee84c 100644
--- a/arch/riscv/mm/Makefile
+++ b/arch/riscv/mm/Makefile
@@ -10,6 +10,7 @@ obj-y += extable.o
 obj-$(CONFIG_MMU) += fault.o
 obj-y += cacheflush.o
 obj-y += context.o
+obj-y += pageattr.o
 
 ifeq ($(CONFIG_MMU),y)
 obj-$(CONFIG_SMP) += tlbflush.o
diff --git a/arch/riscv/mm/pageattr.c b/arch/riscv/mm/pageattr.c
new file mode 100644
index 000000000000..fcd59ef2835b
--- /dev/null
+++ b/arch/riscv/mm/pageattr.c
@@ -0,0 +1,150 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2019 SiFive
+ */
+
+#include <linux/pagewalk.h>
+#include <asm/pgtable.h>
+#include <asm/tlbflush.h>
+#include <asm/bitops.h>
+
+struct pageattr_masks {
+	pgprot_t set_mask;
+	pgprot_t clear_mask;
+};
+
+static unsigned long set_pageattr_masks(unsigned long val, struct mm_walk *walk)
+{
+	struct pageattr_masks *masks = walk->private;
+	unsigned long new_val = val;
+
+	new_val &= ~(pgprot_val(masks->clear_mask));
+	new_val |= (pgprot_val(masks->set_mask));
+
+	return new_val;
+}
+
+static int pageattr_pgd_entry(pgd_t *pgd, unsigned long addr,
+			      unsigned long next, struct mm_walk *walk)
+{
+	pgd_t val = READ_ONCE(*pgd);
+
+	if (pgd_leaf(val)) {
+		val = __pgd(set_pageattr_masks(pgd_val(val), walk));
+		set_pgd(pgd, val);
+	}
+
+	return 0;
+}
+
+static int pageattr_p4d_entry(p4d_t *p4d, unsigned long addr,
+			      unsigned long next, struct mm_walk *walk)
+{
+	p4d_t val = READ_ONCE(*p4d);
+
+	if (p4d_leaf(val)) {
+		val = __p4d(set_pageattr_masks(p4d_val(val), walk));
+		set_p4d(p4d, val);
+	}
+
+	return 0;
+}
+
+static int pageattr_pud_entry(pud_t *pud, unsigned long addr,
+			      unsigned long next, struct mm_walk *walk)
+{
+	pud_t val = READ_ONCE(*pud);
+
+	if (pud_leaf(val)) {
+		val = __pud(set_pageattr_masks(pud_val(val), walk));
+		set_pud(pud, val);
+	}
+
+	return 0;
+}
+
+static int pageattr_pmd_entry(pmd_t *pmd, unsigned long addr,
+			      unsigned long next, struct mm_walk *walk)
+{
+	pmd_t val = READ_ONCE(*pmd);
+
+	if (pmd_leaf(val)) {
+		val = __pmd(set_pageattr_masks(pmd_val(val), walk));
+		set_pmd(pmd, val);
+	}
+
+	return 0;
+}
+
+static int pageattr_pte_entry(pte_t *pte, unsigned long addr,
+			      unsigned long next, struct mm_walk *walk)
+{
+	pte_t val = READ_ONCE(*pte);
+
+	val = __pte(set_pageattr_masks(pte_val(val), walk));
+	set_pte(pte, val);
+
+	return 0;
+}
+
+static int pageattr_pte_hole(unsigned long addr, unsigned long next,
+			     int depth, struct mm_walk *walk)
+{
+	/* Nothing to do here */
+	return 0;
+}
+
+const static struct mm_walk_ops pageattr_ops = {
+	.pgd_entry = pageattr_pgd_entry,
+	.p4d_entry = pageattr_p4d_entry,
+	.pud_entry = pageattr_pud_entry,
+	.pmd_entry = pageattr_pmd_entry,
+	.pte_entry = pageattr_pte_entry,
+	.pte_hole = pageattr_pte_hole,
+};
+
+static int __set_memory(unsigned long addr, int numpages, pgprot_t set_mask,
+			pgprot_t clear_mask)
+{
+	int ret;
+	unsigned long start = addr;
+	unsigned long end = start + PAGE_SIZE * numpages;
+	struct pageattr_masks masks = {
+		.set_mask = set_mask,
+		.clear_mask = clear_mask
+	};
+
+	if (!numpages)
+		return 0;
+
+	down_read(&init_mm.mmap_sem);
+	ret =  walk_page_range_novma(&init_mm, start, end, &pageattr_ops, NULL,
+				     &masks);
+	up_read(&init_mm.mmap_sem);
+
+	flush_tlb_kernel_range(start, end);
+
+	return ret;
+}
+
+int set_memory_ro(unsigned long addr, int numpages)
+{
+	return __set_memory(addr, numpages, __pgprot(_PAGE_READ),
+			    __pgprot(_PAGE_WRITE));
+}
+
+int set_memory_rw(unsigned long addr, int numpages)
+{
+	return __set_memory(addr, numpages, __pgprot(_PAGE_READ | _PAGE_WRITE),
+			    __pgprot(0));
+}
+
+int set_memory_x(unsigned long addr, int numpages)
+{
+	return __set_memory(addr, numpages, __pgprot(_PAGE_EXEC), __pgprot(0));
+}
+
+int set_memory_nx(unsigned long addr, int numpages)
+{
+	return __set_memory(addr, numpages, __pgprot(0), __pgprot(_PAGE_EXEC));
+}
-- 
2.25.0



^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 2/8] riscv: add ARCH_HAS_SET_DIRECT_MAP support
  2020-02-17  8:32 [PATCH 0/8] Support strict kernel memory permissions for security Zong Li
  2020-02-17  8:32 ` [PATCH 1/8] riscv: add ARCH_HAS_SET_MEMORY support Zong Li
@ 2020-02-17  8:32 ` Zong Li
  2020-03-05  0:57   ` Palmer Dabbelt
  2020-02-17  8:32 ` [PATCH 3/8] riscv: add ARCH_SUPPORTS_DEBUG_PAGEALLOC support Zong Li
                   ` (6 subsequent siblings)
  8 siblings, 1 reply; 22+ messages in thread
From: Zong Li @ 2020-02-17  8:32 UTC (permalink / raw)
  To: paul.walmsley, palmer, aou, linux-riscv, linux-kernel; +Cc: Zong Li

Add set_direct_map_*() functions for setting the direct map alias for
the page to its default permissions and to an invalid state that cannot
be cached in a TLB. (See d253ca0c ("x86/mm/cpa: Add set_direct_map_*()
functions")) Add a similar implementation for RISC-V.

Signed-off-by: Zong Li <zong.li@sifive.com>
---
 arch/riscv/Kconfig                  |  1 +
 arch/riscv/include/asm/set_memory.h |  3 +++
 arch/riscv/mm/pageattr.c            | 24 ++++++++++++++++++++++++
 3 files changed, 28 insertions(+)

diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index 76ed36543b3a..07bf1a7c0dd2 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -60,6 +60,7 @@ config RISCV
 	select HAVE_EBPF_JIT if 64BIT
 	select EDAC_SUPPORT
 	select ARCH_HAS_GIGANTIC_PAGE
+	select ARCH_HAS_SET_DIRECT_MAP
 	select ARCH_HAS_SET_MEMORY
 	select ARCH_WANT_HUGE_PMD_SHARE if 64BIT
 	select SPARSEMEM_STATIC if 32BIT
diff --git a/arch/riscv/include/asm/set_memory.h b/arch/riscv/include/asm/set_memory.h
index 936f08063566..a9783a878dca 100644
--- a/arch/riscv/include/asm/set_memory.h
+++ b/arch/riscv/include/asm/set_memory.h
@@ -14,4 +14,7 @@ int set_memory_rw(unsigned long addr, int numpages);
 int set_memory_x(unsigned long addr, int numpages);
 int set_memory_nx(unsigned long addr, int numpages);
 
+int set_direct_map_invalid_noflush(struct page *page);
+int set_direct_map_default_noflush(struct page *page);
+
 #endif /* _ASM_RISCV_SET_MEMORY_H */
diff --git a/arch/riscv/mm/pageattr.c b/arch/riscv/mm/pageattr.c
index fcd59ef2835b..7be6cd67e2ef 100644
--- a/arch/riscv/mm/pageattr.c
+++ b/arch/riscv/mm/pageattr.c
@@ -148,3 +148,27 @@ int set_memory_nx(unsigned long addr, int numpages)
 {
 	return __set_memory(addr, numpages, __pgprot(0), __pgprot(_PAGE_EXEC));
 }
+
+int set_direct_map_invalid_noflush(struct page *page)
+{
+	unsigned long start = (unsigned long)page_address(page);
+	unsigned long end = start + PAGE_SIZE;
+	struct pageattr_masks masks = {
+		.set_mask = __pgprot(0),
+		.clear_mask = __pgprot(_PAGE_PRESENT)
+	};
+
+	return walk_page_range(&init_mm, start, end, &pageattr_ops, &masks);
+}
+
+int set_direct_map_default_noflush(struct page *page)
+{
+	unsigned long start = (unsigned long)page_address(page);
+	unsigned long end = start + PAGE_SIZE;
+	struct pageattr_masks masks = {
+		.set_mask = PAGE_KERNEL,
+		.clear_mask = __pgprot(0)
+	};
+
+	return walk_page_range(&init_mm, start, end, &pageattr_ops, &masks);
+}
-- 
2.25.0



^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 3/8] riscv: add ARCH_SUPPORTS_DEBUG_PAGEALLOC support
  2020-02-17  8:32 [PATCH 0/8] Support strict kernel memory permissions for security Zong Li
  2020-02-17  8:32 ` [PATCH 1/8] riscv: add ARCH_HAS_SET_MEMORY support Zong Li
  2020-02-17  8:32 ` [PATCH 2/8] riscv: add ARCH_HAS_SET_DIRECT_MAP support Zong Li
@ 2020-02-17  8:32 ` Zong Li
  2020-03-05  0:57   ` Palmer Dabbelt
  2020-02-17  8:32 ` [PATCH 4/8] riscv: move exception table immediately after RO_DATA Zong Li
                   ` (5 subsequent siblings)
  8 siblings, 1 reply; 22+ messages in thread
From: Zong Li @ 2020-02-17  8:32 UTC (permalink / raw)
  To: paul.walmsley, palmer, aou, linux-riscv, linux-kernel; +Cc: Zong Li

ARCH_SUPPORTS_DEBUG_PAGEALLOC provides a hook to map and unmap
pages for debugging purposes. Implement the __kernel_map_pages
functions to fill the poison pattern.

Signed-off-by: Zong Li <zong.li@sifive.com>
---
 arch/riscv/Kconfig       |  3 +++
 arch/riscv/mm/pageattr.c | 13 +++++++++++++
 2 files changed, 16 insertions(+)

diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index 07bf1a7c0dd2..f524d7e60648 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -132,6 +132,9 @@ config ARCH_SELECT_MEMORY_MODEL
 config ARCH_WANT_GENERAL_HUGETLB
 	def_bool y
 
+config ARCH_SUPPORTS_DEBUG_PAGEALLOC
+	def_bool y
+
 config SYS_SUPPORTS_HUGETLBFS
 	def_bool y
 
diff --git a/arch/riscv/mm/pageattr.c b/arch/riscv/mm/pageattr.c
index 7be6cd67e2ef..728759eb530a 100644
--- a/arch/riscv/mm/pageattr.c
+++ b/arch/riscv/mm/pageattr.c
@@ -172,3 +172,16 @@ int set_direct_map_default_noflush(struct page *page)
 
 	return walk_page_range(&init_mm, start, end, &pageattr_ops, &masks);
 }
+
+void __kernel_map_pages(struct page *page, int numpages, int enable)
+{
+	if (!debug_pagealloc_enabled())
+		return;
+
+	if (enable)
+		__set_memory((unsigned long)page_address(page), numpages,
+			     __pgprot(_PAGE_PRESENT), __pgprot(0));
+	else
+		__set_memory((unsigned long)page_address(page), numpages,
+			     __pgprot(0), __pgprot(_PAGE_PRESENT));
+}
-- 
2.25.0



^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 4/8] riscv: move exception table immediately after RO_DATA
  2020-02-17  8:32 [PATCH 0/8] Support strict kernel memory permissions for security Zong Li
                   ` (2 preceding siblings ...)
  2020-02-17  8:32 ` [PATCH 3/8] riscv: add ARCH_SUPPORTS_DEBUG_PAGEALLOC support Zong Li
@ 2020-02-17  8:32 ` Zong Li
  2020-03-05  0:57   ` Palmer Dabbelt
  2020-02-17  8:32 ` [PATCH 5/8] riscv: add alignment for text, rodata and data sections Zong Li
                   ` (4 subsequent siblings)
  8 siblings, 1 reply; 22+ messages in thread
From: Zong Li @ 2020-02-17  8:32 UTC (permalink / raw)
  To: paul.walmsley, palmer, aou, linux-riscv, linux-kernel; +Cc: Zong Li

Move EXCEPTION_TABLE immediately after RO_DATA. Make it easy to set the
attribution of the sections which should be read-only at a time.
Move .sdata to indicate the start of data section with write permission.
This patch is prepared for STRICT_KERNEL_RWX support.

Signed-off-by: Zong Li <zong.li@sifive.com>
---
 arch/riscv/kernel/vmlinux.lds.S | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/arch/riscv/kernel/vmlinux.lds.S b/arch/riscv/kernel/vmlinux.lds.S
index 1e0193ded420..4ba8a5397e8b 100644
--- a/arch/riscv/kernel/vmlinux.lds.S
+++ b/arch/riscv/kernel/vmlinux.lds.S
@@ -9,6 +9,7 @@
 #include <asm/page.h>
 #include <asm/cache.h>
 #include <asm/thread_info.h>
+#include <asm/set_memory.h>
 
 OUTPUT_ARCH(riscv)
 ENTRY(_start)
@@ -52,12 +53,15 @@ SECTIONS
 	}
 
 	/* Start of data section */
-	_sdata = .;
 	RO_DATA(L1_CACHE_BYTES)
 	.srodata : {
 		*(.srodata*)
 	}
 
+	EXCEPTION_TABLE(0x10)
+
+	_sdata = .;
+
 	RW_DATA(L1_CACHE_BYTES, PAGE_SIZE, THREAD_SIZE)
 	.sdata : {
 		__global_pointer$ = . + 0x800;
@@ -69,8 +73,6 @@ SECTIONS
 
 	BSS_SECTION(PAGE_SIZE, PAGE_SIZE, 0)
 
-	EXCEPTION_TABLE(0x10)
-
 	.rel.dyn : {
 		*(.rel.dyn*)
 	}
-- 
2.25.0



^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 5/8] riscv: add alignment for text, rodata and data sections
  2020-02-17  8:32 [PATCH 0/8] Support strict kernel memory permissions for security Zong Li
                   ` (3 preceding siblings ...)
  2020-02-17  8:32 ` [PATCH 4/8] riscv: move exception table immediately after RO_DATA Zong Li
@ 2020-02-17  8:32 ` Zong Li
  2020-03-05  0:58   ` Palmer Dabbelt
  2020-02-17  8:32 ` [PATCH 6/8] riscv: add STRICT_KERNEL_RWX support Zong Li
                   ` (3 subsequent siblings)
  8 siblings, 1 reply; 22+ messages in thread
From: Zong Li @ 2020-02-17  8:32 UTC (permalink / raw)
  To: paul.walmsley, palmer, aou, linux-riscv, linux-kernel; +Cc: Zong Li

The kernel mapping will tried to optimize its mapping by using bigger
size. In rv64, it tries to use PMD_SIZE, and tryies to use PGDIR_SIZE in
rv32. To ensure that the start address of these sections could fit the
mapping entry size, make them align to the biggest alignment.

Define a macro SECTION_ALIGN because the HPAGE_SIZE or PMD_SIZE, etc.,
are invisible in linker script.

This patch is prepared for STRICT_KERNEL_RWX support.

Signed-off-by: Zong Li <zong.li@sifive.com>
---
 arch/riscv/include/asm/set_memory.h | 13 +++++++++++++
 arch/riscv/kernel/vmlinux.lds.S     |  4 +++-
 2 files changed, 16 insertions(+), 1 deletion(-)

diff --git a/arch/riscv/include/asm/set_memory.h b/arch/riscv/include/asm/set_memory.h
index a9783a878dca..a91f192063c2 100644
--- a/arch/riscv/include/asm/set_memory.h
+++ b/arch/riscv/include/asm/set_memory.h
@@ -6,6 +6,7 @@
 #ifndef _ASM_RISCV_SET_MEMORY_H
 #define _ASM_RISCV_SET_MEMORY_H
 
+#ifndef __ASSEMBLY__
 /*
  * Functions to change memory attributes.
  */
@@ -17,4 +18,16 @@ int set_memory_nx(unsigned long addr, int numpages);
 int set_direct_map_invalid_noflush(struct page *page);
 int set_direct_map_default_noflush(struct page *page);
 
+#endif /* __ASSEMBLY__ */
+
+#ifdef CONFIG_ARCH_HAS_STRICT_KERNEL_RWX
+#ifdef CONFIG_64BIT
+#define SECTION_ALIGN (1 << 21)
+#else
+#define SECTION_ALIGN (1 << 22)
+#endif
+#else /* !CONFIG_ARCH_HAS_STRICT_KERNEL_RWX */
+#define SECTION_ALIGN L1_CACHE_BYTES
+#endif /* CONFIG_ARCH_HAS_STRICT_KERNEL_RWX */
+
 #endif /* _ASM_RISCV_SET_MEMORY_H */
diff --git a/arch/riscv/kernel/vmlinux.lds.S b/arch/riscv/kernel/vmlinux.lds.S
index 4ba8a5397e8b..0b145b9c1778 100644
--- a/arch/riscv/kernel/vmlinux.lds.S
+++ b/arch/riscv/kernel/vmlinux.lds.S
@@ -37,6 +37,7 @@ SECTIONS
 	PERCPU_SECTION(L1_CACHE_BYTES)
 	__init_end = .;
 
+	. = ALIGN(SECTION_ALIGN);
 	.text : {
 		_text = .;
 		_stext = .;
@@ -53,13 +54,14 @@ SECTIONS
 	}
 
 	/* Start of data section */
-	RO_DATA(L1_CACHE_BYTES)
+	RO_DATA(SECTION_ALIGN)
 	.srodata : {
 		*(.srodata*)
 	}
 
 	EXCEPTION_TABLE(0x10)
 
+	. = ALIGN(SECTION_ALIGN);
 	_sdata = .;
 
 	RW_DATA(L1_CACHE_BYTES, PAGE_SIZE, THREAD_SIZE)
-- 
2.25.0



^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 6/8] riscv: add STRICT_KERNEL_RWX support
  2020-02-17  8:32 [PATCH 0/8] Support strict kernel memory permissions for security Zong Li
                   ` (4 preceding siblings ...)
  2020-02-17  8:32 ` [PATCH 5/8] riscv: add alignment for text, rodata and data sections Zong Li
@ 2020-02-17  8:32 ` Zong Li
  2020-03-05  1:21   ` Palmer Dabbelt
  2020-02-17  8:32 ` [PATCH 7/8] riscv: add DEBUG_WX support Zong Li
                   ` (2 subsequent siblings)
  8 siblings, 1 reply; 22+ messages in thread
From: Zong Li @ 2020-02-17  8:32 UTC (permalink / raw)
  To: paul.walmsley, palmer, aou, linux-riscv, linux-kernel; +Cc: Zong Li

The commit contains that make text section as non-writable, rodata
section as read-only, and data section as non-executable.

The init section should be changed to non-executable.

Signed-off-by: Zong Li <zong.li@sifive.com>
---
 arch/riscv/Kconfig                  |  1 +
 arch/riscv/include/asm/set_memory.h |  8 +++++
 arch/riscv/mm/init.c                | 45 +++++++++++++++++++++++++++++
 3 files changed, 54 insertions(+)

diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index f524d7e60648..308a4dbc0b39 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -62,6 +62,7 @@ config RISCV
 	select ARCH_HAS_GIGANTIC_PAGE
 	select ARCH_HAS_SET_DIRECT_MAP
 	select ARCH_HAS_SET_MEMORY
+	select ARCH_HAS_STRICT_KERNEL_RWX
 	select ARCH_WANT_HUGE_PMD_SHARE if 64BIT
 	select SPARSEMEM_STATIC if 32BIT
 	select ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT if MMU
diff --git a/arch/riscv/include/asm/set_memory.h b/arch/riscv/include/asm/set_memory.h
index a91f192063c2..d3076087cb34 100644
--- a/arch/riscv/include/asm/set_memory.h
+++ b/arch/riscv/include/asm/set_memory.h
@@ -15,6 +15,14 @@ int set_memory_rw(unsigned long addr, int numpages);
 int set_memory_x(unsigned long addr, int numpages);
 int set_memory_nx(unsigned long addr, int numpages);
 
+#ifdef CONFIG_STRICT_KERNEL_RWX
+void set_kernel_text_ro(void);
+void set_kernel_text_rw(void);
+#else
+static inline void set_kernel_text_ro(void) { }
+static inline void set_kernel_text_rw(void) { }
+#endif
+
 int set_direct_map_invalid_noflush(struct page *page);
 int set_direct_map_default_noflush(struct page *page);
 
diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c
index 965a8cf4829c..09fa643e079c 100644
--- a/arch/riscv/mm/init.c
+++ b/arch/riscv/mm/init.c
@@ -12,11 +12,13 @@
 #include <linux/sizes.h>
 #include <linux/of_fdt.h>
 #include <linux/libfdt.h>
+#include <linux/set_memory.h>
 
 #include <asm/fixmap.h>
 #include <asm/tlbflush.h>
 #include <asm/sections.h>
 #include <asm/pgtable.h>
+#include <asm/ptdump.h>
 #include <asm/io.h>
 
 #include "../kernel/head.h"
@@ -477,6 +479,49 @@ static void __init setup_vm_final(void)
 	csr_write(CSR_SATP, PFN_DOWN(__pa_symbol(swapper_pg_dir)) | SATP_MODE);
 	local_flush_tlb_all();
 }
+
+#ifdef CONFIG_STRICT_KERNEL_RWX
+void set_kernel_text_rw(void)
+{
+	unsigned long text_start = (unsigned long)_text;
+	unsigned long text_end = (unsigned long)_etext;
+
+	set_memory_rw(text_start, (text_end - text_start) >> PAGE_SHIFT);
+}
+
+void set_kernel_text_ro(void)
+{
+	unsigned long text_start = (unsigned long)_text;
+	unsigned long text_end = (unsigned long)_etext;
+
+	set_memory_ro(text_start, (text_end - text_start) >> PAGE_SHIFT);
+}
+
+void mark_rodata_ro(void)
+{
+	unsigned long text_start = (unsigned long)_text;
+	unsigned long text_end = (unsigned long)_etext;
+	unsigned long rodata_start = (unsigned long)__start_rodata;
+	unsigned long data_start = (unsigned long)_sdata;
+	unsigned long max_low = (unsigned long)(__va(PFN_PHYS(max_low_pfn)));
+
+	set_memory_ro(text_start, (text_end - text_start) >> PAGE_SHIFT);
+	set_memory_ro(rodata_start, (data_start - rodata_start) >> PAGE_SHIFT);
+	set_memory_nx(rodata_start, (data_start - rodata_start) >> PAGE_SHIFT);
+	set_memory_nx(data_start, (max_low - data_start) >> PAGE_SHIFT);
+}
+#endif
+
+void free_initmem(void)
+{
+	unsigned long init_begin = (unsigned long)__init_begin;
+	unsigned long init_end = (unsigned long)__init_end;
+
+	/* Make the region as non-execuatble. */
+	set_memory_nx(init_begin, (init_end - init_begin) >> PAGE_SHIFT);
+	free_initmem_default(POISON_FREE_INITMEM);
+}
+
 #else
 asmlinkage void __init setup_vm(uintptr_t dtb_pa)
 {
-- 
2.25.0



^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 7/8] riscv: add DEBUG_WX support
  2020-02-17  8:32 [PATCH 0/8] Support strict kernel memory permissions for security Zong Li
                   ` (5 preceding siblings ...)
  2020-02-17  8:32 ` [PATCH 6/8] riscv: add STRICT_KERNEL_RWX support Zong Li
@ 2020-02-17  8:32 ` Zong Li
  2020-03-05  1:44   ` Palmer Dabbelt
  2020-02-17  8:32 ` [PATCH 8/8] riscv: add two hook functions of ftrace Zong Li
  2020-03-05 15:55 ` [PATCH 0/8] Support strict kernel memory permissions for security Palmer Dabbelt
  8 siblings, 1 reply; 22+ messages in thread
From: Zong Li @ 2020-02-17  8:32 UTC (permalink / raw)
  To: paul.walmsley, palmer, aou, linux-riscv, linux-kernel; +Cc: Zong Li

Support DEBUG_WX to check whether there are mapping with write and
execute permission at the same time.

Signed-off-by: Zong Li <zong.li@sifive.com>
---
 arch/riscv/Kconfig.debug        | 30 ++++++++++++++++++++++++++++++
 arch/riscv/include/asm/ptdump.h |  6 ++++++
 arch/riscv/mm/init.c            |  2 ++
 3 files changed, 38 insertions(+)

diff --git a/arch/riscv/Kconfig.debug b/arch/riscv/Kconfig.debug
index e69de29bb2d1..2bcd88e75626 100644
--- a/arch/riscv/Kconfig.debug
+++ b/arch/riscv/Kconfig.debug
@@ -0,0 +1,30 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+config DEBUG_WX
+	bool "Warn on W+X mappings at boot"
+	select PTDUMP_CORE
+	help
+	  Generate a warning if any W+X mappings are found at boot.
+
+	  This is useful for discovering cases where the kernel is leaving
+	  W+X mappings after applying NX, as such mappings are a security risk.
+	  This check also includes UXN, which should be set on all kernel
+	  mappings.
+
+	  Look for a message in dmesg output like this:
+
+	    riscv/mm: Checked W+X mappings: passed, no W+X pages found.
+
+	  or like this, if the check failed:
+
+	    riscv/mm: Checked W+X mappings: FAILED, <N> W+X pages found.
+
+	  Note that even if the check fails, your kernel is possibly
+	  still fine, as W+X mappings are not a security hole in
+	  themselves, what they do is that they make the exploitation
+	  of other unfixed kernel bugs easier.
+
+	  There is no runtime or memory usage effect of this option
+	  once the kernel has booted up - it's a one time check.
+
+	  If in doubt, say "Y".
diff --git a/arch/riscv/include/asm/ptdump.h b/arch/riscv/include/asm/ptdump.h
index e29af7191909..eb2a1cc5f22c 100644
--- a/arch/riscv/include/asm/ptdump.h
+++ b/arch/riscv/include/asm/ptdump.h
@@ -8,4 +8,10 @@
 
 void ptdump_check_wx(void);
 
+#ifdef CONFIG_DEBUG_WX
+#define debug_checkwx() ptdump_check_wx()
+#else
+#define debug_checkwx() do { } while (0)
+#endif
+
 #endif /* _ASM_RISCV_PTDUMP_H */
diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c
index 09fa643e079c..a05d76e5fefe 100644
--- a/arch/riscv/mm/init.c
+++ b/arch/riscv/mm/init.c
@@ -509,6 +509,8 @@ void mark_rodata_ro(void)
 	set_memory_ro(rodata_start, (data_start - rodata_start) >> PAGE_SHIFT);
 	set_memory_nx(rodata_start, (data_start - rodata_start) >> PAGE_SHIFT);
 	set_memory_nx(data_start, (max_low - data_start) >> PAGE_SHIFT);
+
+	debug_checkwx();
 }
 #endif
 
-- 
2.25.0



^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 8/8] riscv: add two hook functions of ftrace
  2020-02-17  8:32 [PATCH 0/8] Support strict kernel memory permissions for security Zong Li
                   ` (6 preceding siblings ...)
  2020-02-17  8:32 ` [PATCH 7/8] riscv: add DEBUG_WX support Zong Li
@ 2020-02-17  8:32 ` Zong Li
  2020-03-05  1:44   ` Palmer Dabbelt
  2020-03-05 15:55 ` [PATCH 0/8] Support strict kernel memory permissions for security Palmer Dabbelt
  8 siblings, 1 reply; 22+ messages in thread
From: Zong Li @ 2020-02-17  8:32 UTC (permalink / raw)
  To: paul.walmsley, palmer, aou, linux-riscv, linux-kernel; +Cc: Zong Li

After the text section be mask as non-writable, the ftrace have to
change the permission of text for dynamic patching the intructions.
Add ftrace_arch_code_modify_prepare and
ftrace_arch_code_modify_post_process to change permission.

Signed-off-by: Zong Li <zong.li@sifive.com>
---
 arch/riscv/kernel/ftrace.c | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/arch/riscv/kernel/ftrace.c b/arch/riscv/kernel/ftrace.c
index c40fdcdeb950..576df0807200 100644
--- a/arch/riscv/kernel/ftrace.c
+++ b/arch/riscv/kernel/ftrace.c
@@ -7,9 +7,27 @@
 
 #include <linux/ftrace.h>
 #include <linux/uaccess.h>
+#include <linux/memory.h>
+#include <asm/set_memory.h>
 #include <asm/cacheflush.h>
 
 #ifdef CONFIG_DYNAMIC_FTRACE
+int ftrace_arch_code_modify_prepare(void) __acquires(&text_mutex)
+{
+	mutex_lock(&text_mutex);
+	set_kernel_text_rw();
+	set_all_modules_text_rw();
+	return 0;
+}
+
+int ftrace_arch_code_modify_post_process(void) __releases(&text_mutex)
+{
+	set_all_modules_text_ro();
+	set_kernel_text_ro();
+	mutex_unlock(&text_mutex);
+	return 0;
+}
+
 static int ftrace_check_current_call(unsigned long hook_pos,
 				     unsigned int *expected)
 {
-- 
2.25.0



^ permalink raw reply related	[flat|nested] 22+ messages in thread

* Re: [PATCH 1/8] riscv: add ARCH_HAS_SET_MEMORY support
  2020-02-17  8:32 ` [PATCH 1/8] riscv: add ARCH_HAS_SET_MEMORY support Zong Li
@ 2020-03-05  0:57   ` Palmer Dabbelt
  0 siblings, 0 replies; 22+ messages in thread
From: Palmer Dabbelt @ 2020-03-05  0:57 UTC (permalink / raw)
  To: zong.li; +Cc: linux-riscv, aou, linux-kernel, zong.li, Paul Walmsley

On Mon, 17 Feb 2020 00:32:16 PST (-0800), zong.li@sifive.com wrote:
> Add set_memory_ro/rw/x/nx architecture hooks to change the page
> attribution.
>
> Use own set_memory.h rather than generic set_memory.h
> (i.e. include/asm-generic/set_memory.h), because we want to add other
> function prototypes here.
>
> Signed-off-by: Zong Li <zong.li@sifive.com>
> ---
>  arch/riscv/Kconfig                  |   1 +
>  arch/riscv/include/asm/set_memory.h |  17 ++++
>  arch/riscv/mm/Makefile              |   1 +
>  arch/riscv/mm/pageattr.c            | 150 ++++++++++++++++++++++++++++
>  4 files changed, 169 insertions(+)
>  create mode 100644 arch/riscv/include/asm/set_memory.h
>  create mode 100644 arch/riscv/mm/pageattr.c
>
> diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
> index 6e81da55b5e4..76ed36543b3a 100644
> --- a/arch/riscv/Kconfig
> +++ b/arch/riscv/Kconfig
> @@ -60,6 +60,7 @@ config RISCV
>  	select HAVE_EBPF_JIT if 64BIT
>  	select EDAC_SUPPORT
>  	select ARCH_HAS_GIGANTIC_PAGE
> +	select ARCH_HAS_SET_MEMORY
>  	select ARCH_WANT_HUGE_PMD_SHARE if 64BIT
>  	select SPARSEMEM_STATIC if 32BIT
>  	select ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT if MMU
> diff --git a/arch/riscv/include/asm/set_memory.h b/arch/riscv/include/asm/set_memory.h
> new file mode 100644
> index 000000000000..936f08063566
> --- /dev/null
> +++ b/arch/riscv/include/asm/set_memory.h
> @@ -0,0 +1,17 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +/*
> + * Copyright (C) 2019 SiFive
> + */
> +
> +#ifndef _ASM_RISCV_SET_MEMORY_H
> +#define _ASM_RISCV_SET_MEMORY_H
> +
> +/*
> + * Functions to change memory attributes.
> + */
> +int set_memory_ro(unsigned long addr, int numpages);
> +int set_memory_rw(unsigned long addr, int numpages);
> +int set_memory_x(unsigned long addr, int numpages);
> +int set_memory_nx(unsigned long addr, int numpages);
> +
> +#endif /* _ASM_RISCV_SET_MEMORY_H */
> diff --git a/arch/riscv/mm/Makefile b/arch/riscv/mm/Makefile
> index 814e16a8d68a..b94643aee84c 100644
> --- a/arch/riscv/mm/Makefile
> +++ b/arch/riscv/mm/Makefile
> @@ -10,6 +10,7 @@ obj-y += extable.o
>  obj-$(CONFIG_MMU) += fault.o
>  obj-y += cacheflush.o
>  obj-y += context.o
> +obj-y += pageattr.o
>
>  ifeq ($(CONFIG_MMU),y)
>  obj-$(CONFIG_SMP) += tlbflush.o
> diff --git a/arch/riscv/mm/pageattr.c b/arch/riscv/mm/pageattr.c
> new file mode 100644
> index 000000000000..fcd59ef2835b
> --- /dev/null
> +++ b/arch/riscv/mm/pageattr.c
> @@ -0,0 +1,150 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (C) 2019 SiFive
> + */
> +
> +#include <linux/pagewalk.h>
> +#include <asm/pgtable.h>
> +#include <asm/tlbflush.h>
> +#include <asm/bitops.h>
> +
> +struct pageattr_masks {
> +	pgprot_t set_mask;
> +	pgprot_t clear_mask;
> +};
> +
> +static unsigned long set_pageattr_masks(unsigned long val, struct mm_walk *walk)
> +{
> +	struct pageattr_masks *masks = walk->private;
> +	unsigned long new_val = val;
> +
> +	new_val &= ~(pgprot_val(masks->clear_mask));
> +	new_val |= (pgprot_val(masks->set_mask));
> +
> +	return new_val;
> +}
> +
> +static int pageattr_pgd_entry(pgd_t *pgd, unsigned long addr,
> +			      unsigned long next, struct mm_walk *walk)
> +{
> +	pgd_t val = READ_ONCE(*pgd);
> +
> +	if (pgd_leaf(val)) {
> +		val = __pgd(set_pageattr_masks(pgd_val(val), walk));
> +		set_pgd(pgd, val);
> +	}
> +
> +	return 0;
> +}
> +
> +static int pageattr_p4d_entry(p4d_t *p4d, unsigned long addr,
> +			      unsigned long next, struct mm_walk *walk)
> +{
> +	p4d_t val = READ_ONCE(*p4d);
> +
> +	if (p4d_leaf(val)) {
> +		val = __p4d(set_pageattr_masks(p4d_val(val), walk));
> +		set_p4d(p4d, val);
> +	}
> +
> +	return 0;
> +}
> +
> +static int pageattr_pud_entry(pud_t *pud, unsigned long addr,
> +			      unsigned long next, struct mm_walk *walk)
> +{
> +	pud_t val = READ_ONCE(*pud);
> +
> +	if (pud_leaf(val)) {
> +		val = __pud(set_pageattr_masks(pud_val(val), walk));
> +		set_pud(pud, val);
> +	}
> +
> +	return 0;
> +}
> +
> +static int pageattr_pmd_entry(pmd_t *pmd, unsigned long addr,
> +			      unsigned long next, struct mm_walk *walk)
> +{
> +	pmd_t val = READ_ONCE(*pmd);
> +
> +	if (pmd_leaf(val)) {
> +		val = __pmd(set_pageattr_masks(pmd_val(val), walk));
> +		set_pmd(pmd, val);
> +	}
> +
> +	return 0;
> +}
> +
> +static int pageattr_pte_entry(pte_t *pte, unsigned long addr,
> +			      unsigned long next, struct mm_walk *walk)
> +{
> +	pte_t val = READ_ONCE(*pte);
> +
> +	val = __pte(set_pageattr_masks(pte_val(val), walk));
> +	set_pte(pte, val);
> +
> +	return 0;
> +}
> +
> +static int pageattr_pte_hole(unsigned long addr, unsigned long next,
> +			     int depth, struct mm_walk *walk)
> +{
> +	/* Nothing to do here */
> +	return 0;
> +}
> +
> +const static struct mm_walk_ops pageattr_ops = {
> +	.pgd_entry = pageattr_pgd_entry,
> +	.p4d_entry = pageattr_p4d_entry,
> +	.pud_entry = pageattr_pud_entry,
> +	.pmd_entry = pageattr_pmd_entry,
> +	.pte_entry = pageattr_pte_entry,
> +	.pte_hole = pageattr_pte_hole,
> +};
> +
> +static int __set_memory(unsigned long addr, int numpages, pgprot_t set_mask,
> +			pgprot_t clear_mask)
> +{
> +	int ret;
> +	unsigned long start = addr;
> +	unsigned long end = start + PAGE_SIZE * numpages;
> +	struct pageattr_masks masks = {
> +		.set_mask = set_mask,
> +		.clear_mask = clear_mask
> +	};
> +
> +	if (!numpages)
> +		return 0;
> +
> +	down_read(&init_mm.mmap_sem);
> +	ret =  walk_page_range_novma(&init_mm, start, end, &pageattr_ops, NULL,
> +				     &masks);
> +	up_read(&init_mm.mmap_sem);

There are very few users of _novma, but I think it's correct here.

> +
> +	flush_tlb_kernel_range(start, end);
> +
> +	return ret;
> +}
> +
> +int set_memory_ro(unsigned long addr, int numpages)
> +{
> +	return __set_memory(addr, numpages, __pgprot(_PAGE_READ),
> +			    __pgprot(_PAGE_WRITE));
> +}
> +
> +int set_memory_rw(unsigned long addr, int numpages)
> +{
> +	return __set_memory(addr, numpages, __pgprot(_PAGE_READ | _PAGE_WRITE),
> +			    __pgprot(0));
> +}
> +
> +int set_memory_x(unsigned long addr, int numpages)
> +{
> +	return __set_memory(addr, numpages, __pgprot(_PAGE_EXEC), __pgprot(0));
> +}
> +
> +int set_memory_nx(unsigned long addr, int numpages)
> +{
> +	return __set_memory(addr, numpages, __pgprot(0), __pgprot(_PAGE_EXEC));
> +}

Reviewed-by: Palmer Dabbelt <palmerdabbelt@google.com>

Thanks!


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 2/8] riscv: add ARCH_HAS_SET_DIRECT_MAP support
  2020-02-17  8:32 ` [PATCH 2/8] riscv: add ARCH_HAS_SET_DIRECT_MAP support Zong Li
@ 2020-03-05  0:57   ` Palmer Dabbelt
  0 siblings, 0 replies; 22+ messages in thread
From: Palmer Dabbelt @ 2020-03-05  0:57 UTC (permalink / raw)
  To: zong.li; +Cc: linux-riscv, aou, linux-kernel, zong.li, Paul Walmsley

On Mon, 17 Feb 2020 00:32:17 PST (-0800), zong.li@sifive.com wrote:
> Add set_direct_map_*() functions for setting the direct map alias for
> the page to its default permissions and to an invalid state that cannot
> be cached in a TLB. (See d253ca0c ("x86/mm/cpa: Add set_direct_map_*()
> functions")) Add a similar implementation for RISC-V.
>
> Signed-off-by: Zong Li <zong.li@sifive.com>
> ---
>  arch/riscv/Kconfig                  |  1 +
>  arch/riscv/include/asm/set_memory.h |  3 +++
>  arch/riscv/mm/pageattr.c            | 24 ++++++++++++++++++++++++
>  3 files changed, 28 insertions(+)
>
> diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
> index 76ed36543b3a..07bf1a7c0dd2 100644
> --- a/arch/riscv/Kconfig
> +++ b/arch/riscv/Kconfig
> @@ -60,6 +60,7 @@ config RISCV
>  	select HAVE_EBPF_JIT if 64BIT
>  	select EDAC_SUPPORT
>  	select ARCH_HAS_GIGANTIC_PAGE
> +	select ARCH_HAS_SET_DIRECT_MAP
>  	select ARCH_HAS_SET_MEMORY
>  	select ARCH_WANT_HUGE_PMD_SHARE if 64BIT
>  	select SPARSEMEM_STATIC if 32BIT
> diff --git a/arch/riscv/include/asm/set_memory.h b/arch/riscv/include/asm/set_memory.h
> index 936f08063566..a9783a878dca 100644
> --- a/arch/riscv/include/asm/set_memory.h
> +++ b/arch/riscv/include/asm/set_memory.h
> @@ -14,4 +14,7 @@ int set_memory_rw(unsigned long addr, int numpages);
>  int set_memory_x(unsigned long addr, int numpages);
>  int set_memory_nx(unsigned long addr, int numpages);
>
> +int set_direct_map_invalid_noflush(struct page *page);
> +int set_direct_map_default_noflush(struct page *page);
> +
>  #endif /* _ASM_RISCV_SET_MEMORY_H */
> diff --git a/arch/riscv/mm/pageattr.c b/arch/riscv/mm/pageattr.c
> index fcd59ef2835b..7be6cd67e2ef 100644
> --- a/arch/riscv/mm/pageattr.c
> +++ b/arch/riscv/mm/pageattr.c
> @@ -148,3 +148,27 @@ int set_memory_nx(unsigned long addr, int numpages)
>  {
>  	return __set_memory(addr, numpages, __pgprot(0), __pgprot(_PAGE_EXEC));
>  }
> +
> +int set_direct_map_invalid_noflush(struct page *page)
> +{
> +	unsigned long start = (unsigned long)page_address(page);
> +	unsigned long end = start + PAGE_SIZE;
> +	struct pageattr_masks masks = {
> +		.set_mask = __pgprot(0),
> +		.clear_mask = __pgprot(_PAGE_PRESENT)
> +	};
> +
> +	return walk_page_range(&init_mm, start, end, &pageattr_ops, &masks);
> +}
> +
> +int set_direct_map_default_noflush(struct page *page)
> +{
> +	unsigned long start = (unsigned long)page_address(page);
> +	unsigned long end = start + PAGE_SIZE;
> +	struct pageattr_masks masks = {
> +		.set_mask = PAGE_KERNEL,
> +		.clear_mask = __pgprot(0)
> +	};
> +
> +	return walk_page_range(&init_mm, start, end, &pageattr_ops, &masks);
> +}

Reviewed-by: Palmer Dabbelt <palmerdabbelt@google.com>


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 3/8] riscv: add ARCH_SUPPORTS_DEBUG_PAGEALLOC support
  2020-02-17  8:32 ` [PATCH 3/8] riscv: add ARCH_SUPPORTS_DEBUG_PAGEALLOC support Zong Li
@ 2020-03-05  0:57   ` Palmer Dabbelt
  0 siblings, 0 replies; 22+ messages in thread
From: Palmer Dabbelt @ 2020-03-05  0:57 UTC (permalink / raw)
  To: zong.li; +Cc: linux-riscv, aou, linux-kernel, zong.li, Paul Walmsley

On Mon, 17 Feb 2020 00:32:18 PST (-0800), zong.li@sifive.com wrote:
> ARCH_SUPPORTS_DEBUG_PAGEALLOC provides a hook to map and unmap
> pages for debugging purposes. Implement the __kernel_map_pages
> functions to fill the poison pattern.
>
> Signed-off-by: Zong Li <zong.li@sifive.com>
> ---
>  arch/riscv/Kconfig       |  3 +++
>  arch/riscv/mm/pageattr.c | 13 +++++++++++++
>  2 files changed, 16 insertions(+)
>
> diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
> index 07bf1a7c0dd2..f524d7e60648 100644
> --- a/arch/riscv/Kconfig
> +++ b/arch/riscv/Kconfig
> @@ -132,6 +132,9 @@ config ARCH_SELECT_MEMORY_MODEL
>  config ARCH_WANT_GENERAL_HUGETLB
>  	def_bool y
>
> +config ARCH_SUPPORTS_DEBUG_PAGEALLOC
> +	def_bool y
> +
>  config SYS_SUPPORTS_HUGETLBFS
>  	def_bool y
>
> diff --git a/arch/riscv/mm/pageattr.c b/arch/riscv/mm/pageattr.c
> index 7be6cd67e2ef..728759eb530a 100644
> --- a/arch/riscv/mm/pageattr.c
> +++ b/arch/riscv/mm/pageattr.c
> @@ -172,3 +172,16 @@ int set_direct_map_default_noflush(struct page *page)
>
>  	return walk_page_range(&init_mm, start, end, &pageattr_ops, &masks);
>  }
> +
> +void __kernel_map_pages(struct page *page, int numpages, int enable)
> +{
> +	if (!debug_pagealloc_enabled())
> +		return;
> +
> +	if (enable)
> +		__set_memory((unsigned long)page_address(page), numpages,
> +			     __pgprot(_PAGE_PRESENT), __pgprot(0));
> +	else
> +		__set_memory((unsigned long)page_address(page), numpages,
> +			     __pgprot(0), __pgprot(_PAGE_PRESENT));
> +}

Reviewed-by: Palmer Dabbelt <palmerdabbelt@google.com>


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 4/8] riscv: move exception table immediately after RO_DATA
  2020-02-17  8:32 ` [PATCH 4/8] riscv: move exception table immediately after RO_DATA Zong Li
@ 2020-03-05  0:57   ` Palmer Dabbelt
  2020-03-05  4:01     ` Zong Li
  0 siblings, 1 reply; 22+ messages in thread
From: Palmer Dabbelt @ 2020-03-05  0:57 UTC (permalink / raw)
  To: zong.li; +Cc: linux-riscv, aou, linux-kernel, zong.li, Paul Walmsley

On Mon, 17 Feb 2020 00:32:19 PST (-0800), zong.li@sifive.com wrote:
> Move EXCEPTION_TABLE immediately after RO_DATA. Make it easy to set the
> attribution of the sections which should be read-only at a time.
> Move .sdata to indicate the start of data section with write permission.
> This patch is prepared for STRICT_KERNEL_RWX support.
>
> Signed-off-by: Zong Li <zong.li@sifive.com>
> ---
>  arch/riscv/kernel/vmlinux.lds.S | 8 +++++---
>  1 file changed, 5 insertions(+), 3 deletions(-)
>
> diff --git a/arch/riscv/kernel/vmlinux.lds.S b/arch/riscv/kernel/vmlinux.lds.S
> index 1e0193ded420..4ba8a5397e8b 100644
> --- a/arch/riscv/kernel/vmlinux.lds.S
> +++ b/arch/riscv/kernel/vmlinux.lds.S
> @@ -9,6 +9,7 @@
>  #include <asm/page.h>
>  #include <asm/cache.h>
>  #include <asm/thread_info.h>
> +#include <asm/set_memory.h>
>
>  OUTPUT_ARCH(riscv)
>  ENTRY(_start)
> @@ -52,12 +53,15 @@ SECTIONS
>  	}
>
>  	/* Start of data section */
> -	_sdata = .;
>  	RO_DATA(L1_CACHE_BYTES)
>  	.srodata : {
>  		*(.srodata*)
>  	}
>
> +	EXCEPTION_TABLE(0x10)
> +
> +	_sdata = .;
> +
>  	RW_DATA(L1_CACHE_BYTES, PAGE_SIZE, THREAD_SIZE)
>  	.sdata : {
>  		__global_pointer$ = . + 0x800;
> @@ -69,8 +73,6 @@ SECTIONS
>
>  	BSS_SECTION(PAGE_SIZE, PAGE_SIZE, 0)
>
> -	EXCEPTION_TABLE(0x10)
> -
>  	.rel.dyn : {
>  		*(.rel.dyn*)
>  	}

As far as I can tell this is OK: core_kernel_data() explicitly says that RODATA
may or may not be between _sdata and _edata.  That said, I think we should add
__start_rodata and __end_rodata atomicly with this change (around RO_DATA and
.srodata).


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 5/8] riscv: add alignment for text, rodata and data sections
  2020-02-17  8:32 ` [PATCH 5/8] riscv: add alignment for text, rodata and data sections Zong Li
@ 2020-03-05  0:58   ` Palmer Dabbelt
  0 siblings, 0 replies; 22+ messages in thread
From: Palmer Dabbelt @ 2020-03-05  0:58 UTC (permalink / raw)
  To: zong.li; +Cc: linux-riscv, aou, linux-kernel, zong.li, Paul Walmsley

On Mon, 17 Feb 2020 00:32:20 PST (-0800), zong.li@sifive.com wrote:
> The kernel mapping will tried to optimize its mapping by using bigger
> size. In rv64, it tries to use PMD_SIZE, and tryies to use PGDIR_SIZE in
> rv32. To ensure that the start address of these sections could fit the
> mapping entry size, make them align to the biggest alignment.
>
> Define a macro SECTION_ALIGN because the HPAGE_SIZE or PMD_SIZE, etc.,
> are invisible in linker script.
>
> This patch is prepared for STRICT_KERNEL_RWX support.
>
> Signed-off-by: Zong Li <zong.li@sifive.com>
> ---
>  arch/riscv/include/asm/set_memory.h | 13 +++++++++++++
>  arch/riscv/kernel/vmlinux.lds.S     |  4 +++-
>  2 files changed, 16 insertions(+), 1 deletion(-)
>
> diff --git a/arch/riscv/include/asm/set_memory.h b/arch/riscv/include/asm/set_memory.h
> index a9783a878dca..a91f192063c2 100644
> --- a/arch/riscv/include/asm/set_memory.h
> +++ b/arch/riscv/include/asm/set_memory.h
> @@ -6,6 +6,7 @@
>  #ifndef _ASM_RISCV_SET_MEMORY_H
>  #define _ASM_RISCV_SET_MEMORY_H
>
> +#ifndef __ASSEMBLY__
>  /*
>   * Functions to change memory attributes.
>   */
> @@ -17,4 +18,16 @@ int set_memory_nx(unsigned long addr, int numpages);
>  int set_direct_map_invalid_noflush(struct page *page);
>  int set_direct_map_default_noflush(struct page *page);
>
> +#endif /* __ASSEMBLY__ */
> +
> +#ifdef CONFIG_ARCH_HAS_STRICT_KERNEL_RWX
> +#ifdef CONFIG_64BIT
> +#define SECTION_ALIGN (1 << 21)
> +#else
> +#define SECTION_ALIGN (1 << 22)
> +#endif
> +#else /* !CONFIG_ARCH_HAS_STRICT_KERNEL_RWX */
> +#define SECTION_ALIGN L1_CACHE_BYTES
> +#endif /* CONFIG_ARCH_HAS_STRICT_KERNEL_RWX */
> +
>  #endif /* _ASM_RISCV_SET_MEMORY_H */
> diff --git a/arch/riscv/kernel/vmlinux.lds.S b/arch/riscv/kernel/vmlinux.lds.S
> index 4ba8a5397e8b..0b145b9c1778 100644
> --- a/arch/riscv/kernel/vmlinux.lds.S
> +++ b/arch/riscv/kernel/vmlinux.lds.S
> @@ -37,6 +37,7 @@ SECTIONS
>  	PERCPU_SECTION(L1_CACHE_BYTES)
>  	__init_end = .;
>
> +	. = ALIGN(SECTION_ALIGN);
>  	.text : {
>  		_text = .;
>  		_stext = .;
> @@ -53,13 +54,14 @@ SECTIONS
>  	}
>
>  	/* Start of data section */
> -	RO_DATA(L1_CACHE_BYTES)
> +	RO_DATA(SECTION_ALIGN)
>  	.srodata : {
>  		*(.srodata*)
>  	}
>
>  	EXCEPTION_TABLE(0x10)
>
> +	. = ALIGN(SECTION_ALIGN);
>  	_sdata = .;
>
>  	RW_DATA(L1_CACHE_BYTES, PAGE_SIZE, THREAD_SIZE)

Reviewed-by: Palmer Dabbelt <palmerdabbelt@google.com>


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 6/8] riscv: add STRICT_KERNEL_RWX support
  2020-02-17  8:32 ` [PATCH 6/8] riscv: add STRICT_KERNEL_RWX support Zong Li
@ 2020-03-05  1:21   ` Palmer Dabbelt
  2020-03-05  4:08     ` Zong Li
  0 siblings, 1 reply; 22+ messages in thread
From: Palmer Dabbelt @ 2020-03-05  1:21 UTC (permalink / raw)
  To: zong.li; +Cc: linux-riscv, aou, linux-kernel, zong.li, Paul Walmsley

On Mon, 17 Feb 2020 00:32:21 PST (-0800), zong.li@sifive.com wrote:
> The commit contains that make text section as non-writable, rodata
> section as read-only, and data section as non-executable.
>
> The init section should be changed to non-executable.
>
> Signed-off-by: Zong Li <zong.li@sifive.com>
> ---
>  arch/riscv/Kconfig                  |  1 +
>  arch/riscv/include/asm/set_memory.h |  8 +++++
>  arch/riscv/mm/init.c                | 45 +++++++++++++++++++++++++++++
>  3 files changed, 54 insertions(+)
>
> diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
> index f524d7e60648..308a4dbc0b39 100644
> --- a/arch/riscv/Kconfig
> +++ b/arch/riscv/Kconfig
> @@ -62,6 +62,7 @@ config RISCV
>  	select ARCH_HAS_GIGANTIC_PAGE
>  	select ARCH_HAS_SET_DIRECT_MAP
>  	select ARCH_HAS_SET_MEMORY
> +	select ARCH_HAS_STRICT_KERNEL_RWX
>  	select ARCH_WANT_HUGE_PMD_SHARE if 64BIT
>  	select SPARSEMEM_STATIC if 32BIT
>  	select ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT if MMU
> diff --git a/arch/riscv/include/asm/set_memory.h b/arch/riscv/include/asm/set_memory.h
> index a91f192063c2..d3076087cb34 100644
> --- a/arch/riscv/include/asm/set_memory.h
> +++ b/arch/riscv/include/asm/set_memory.h
> @@ -15,6 +15,14 @@ int set_memory_rw(unsigned long addr, int numpages);
>  int set_memory_x(unsigned long addr, int numpages);
>  int set_memory_nx(unsigned long addr, int numpages);
>
> +#ifdef CONFIG_STRICT_KERNEL_RWX
> +void set_kernel_text_ro(void);
> +void set_kernel_text_rw(void);
> +#else
> +static inline void set_kernel_text_ro(void) { }
> +static inline void set_kernel_text_rw(void) { }
> +#endif
> +
>  int set_direct_map_invalid_noflush(struct page *page);
>  int set_direct_map_default_noflush(struct page *page);
>
> diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c
> index 965a8cf4829c..09fa643e079c 100644
> --- a/arch/riscv/mm/init.c
> +++ b/arch/riscv/mm/init.c
> @@ -12,11 +12,13 @@
>  #include <linux/sizes.h>
>  #include <linux/of_fdt.h>
>  #include <linux/libfdt.h>
> +#include <linux/set_memory.h>
>
>  #include <asm/fixmap.h>
>  #include <asm/tlbflush.h>
>  #include <asm/sections.h>
>  #include <asm/pgtable.h>
> +#include <asm/ptdump.h>
>  #include <asm/io.h>
>
>  #include "../kernel/head.h"
> @@ -477,6 +479,49 @@ static void __init setup_vm_final(void)
>  	csr_write(CSR_SATP, PFN_DOWN(__pa_symbol(swapper_pg_dir)) | SATP_MODE);
>  	local_flush_tlb_all();
>  }
> +
> +#ifdef CONFIG_STRICT_KERNEL_RWX
> +void set_kernel_text_rw(void)
> +{
> +	unsigned long text_start = (unsigned long)_text;
> +	unsigned long text_end = (unsigned long)_etext;
> +
> +	set_memory_rw(text_start, (text_end - text_start) >> PAGE_SHIFT);
> +}
> +
> +void set_kernel_text_ro(void)
> +{
> +	unsigned long text_start = (unsigned long)_text;
> +	unsigned long text_end = (unsigned long)_etext;
> +
> +	set_memory_ro(text_start, (text_end - text_start) >> PAGE_SHIFT);
> +}
> +
> +void mark_rodata_ro(void)
> +{
> +	unsigned long text_start = (unsigned long)_text;
> +	unsigned long text_end = (unsigned long)_etext;
> +	unsigned long rodata_start = (unsigned long)__start_rodata;
> +	unsigned long data_start = (unsigned long)_sdata;
> +	unsigned long max_low = (unsigned long)(__va(PFN_PHYS(max_low_pfn)));
> +
> +	set_memory_ro(text_start, (text_end - text_start) >> PAGE_SHIFT);
> +	set_memory_ro(rodata_start, (data_start - rodata_start) >> PAGE_SHIFT);
> +	set_memory_nx(rodata_start, (data_start - rodata_start) >> PAGE_SHIFT);

Ya, this'll risk barfing because of srodata.

> +	set_memory_nx(data_start, (max_low - data_start) >> PAGE_SHIFT);
> +}
> +#endif
> +
> +void free_initmem(void)
> +{
> +	unsigned long init_begin = (unsigned long)__init_begin;
> +	unsigned long init_end = (unsigned long)__init_end;
> +
> +	/* Make the region as non-execuatble. */
> +	set_memory_nx(init_begin, (init_end - init_begin) >> PAGE_SHIFT);
> +	free_initmem_default(POISON_FREE_INITMEM);
> +}
> +
>  #else
>  asmlinkage void __init setup_vm(uintptr_t dtb_pa)
>  {


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 7/8] riscv: add DEBUG_WX support
  2020-02-17  8:32 ` [PATCH 7/8] riscv: add DEBUG_WX support Zong Li
@ 2020-03-05  1:44   ` Palmer Dabbelt
  2020-03-05  5:53     ` Zong Li
  0 siblings, 1 reply; 22+ messages in thread
From: Palmer Dabbelt @ 2020-03-05  1:44 UTC (permalink / raw)
  To: zong.li; +Cc: linux-riscv, aou, linux-kernel, zong.li, Paul Walmsley

On Mon, 17 Feb 2020 00:32:22 PST (-0800), zong.li@sifive.com wrote:
> Support DEBUG_WX to check whether there are mapping with write and
> execute permission at the same time.
>
> Signed-off-by: Zong Li <zong.li@sifive.com>
> ---
>  arch/riscv/Kconfig.debug        | 30 ++++++++++++++++++++++++++++++
>  arch/riscv/include/asm/ptdump.h |  6 ++++++
>  arch/riscv/mm/init.c            |  2 ++
>  3 files changed, 38 insertions(+)
>
> diff --git a/arch/riscv/Kconfig.debug b/arch/riscv/Kconfig.debug
> index e69de29bb2d1..2bcd88e75626 100644
> --- a/arch/riscv/Kconfig.debug
> +++ b/arch/riscv/Kconfig.debug
> @@ -0,0 +1,30 @@
> +# SPDX-License-Identifier: GPL-2.0-only
> +
> +config DEBUG_WX
> +	bool "Warn on W+X mappings at boot"
> +	select PTDUMP_CORE
> +	help
> +	  Generate a warning if any W+X mappings are found at boot.
> +
> +	  This is useful for discovering cases where the kernel is leaving
> +	  W+X mappings after applying NX, as such mappings are a security risk.
> +	  This check also includes UXN, which should be set on all kernel
> +	  mappings.
> +
> +	  Look for a message in dmesg output like this:
> +
> +	    riscv/mm: Checked W+X mappings: passed, no W+X pages found.
> +
> +	  or like this, if the check failed:
> +
> +	    riscv/mm: Checked W+X mappings: FAILED, <N> W+X pages found.
> +
> +	  Note that even if the check fails, your kernel is possibly
> +	  still fine, as W+X mappings are not a security hole in
> +	  themselves, what they do is that they make the exploitation
> +	  of other unfixed kernel bugs easier.
> +
> +	  There is no runtime or memory usage effect of this option
> +	  once the kernel has booted up - it's a one time check.
> +
> +	  If in doubt, say "Y".

It looks like this comes verbatim from the arm64 port, at least.  I think we
should just refactor this to some sort of ARCH_HAS_DEBUG_WX so we can share the
code.  I usually do this by adding the shared support, using it for RISC-V, and
then converting the other ports over.

> diff --git a/arch/riscv/include/asm/ptdump.h b/arch/riscv/include/asm/ptdump.h
> index e29af7191909..eb2a1cc5f22c 100644
> --- a/arch/riscv/include/asm/ptdump.h
> +++ b/arch/riscv/include/asm/ptdump.h
> @@ -8,4 +8,10 @@
>
>  void ptdump_check_wx(void);
>
> +#ifdef CONFIG_DEBUG_WX
> +#define debug_checkwx() ptdump_check_wx()
> +#else
> +#define debug_checkwx() do { } while (0)
> +#endif
> +
>  #endif /* _ASM_RISCV_PTDUMP_H */
> diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c
> index 09fa643e079c..a05d76e5fefe 100644
> --- a/arch/riscv/mm/init.c
> +++ b/arch/riscv/mm/init.c
> @@ -509,6 +509,8 @@ void mark_rodata_ro(void)
>  	set_memory_ro(rodata_start, (data_start - rodata_start) >> PAGE_SHIFT);
>  	set_memory_nx(rodata_start, (data_start - rodata_start) >> PAGE_SHIFT);
>  	set_memory_nx(data_start, (max_low - data_start) >> PAGE_SHIFT);
> +
> +	debug_checkwx();
>  }
>  #endif


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 8/8] riscv: add two hook functions of ftrace
  2020-02-17  8:32 ` [PATCH 8/8] riscv: add two hook functions of ftrace Zong Li
@ 2020-03-05  1:44   ` Palmer Dabbelt
  2020-03-05  4:27     ` Zong Li
  0 siblings, 1 reply; 22+ messages in thread
From: Palmer Dabbelt @ 2020-03-05  1:44 UTC (permalink / raw)
  To: zong.li; +Cc: linux-riscv, aou, linux-kernel, zong.li, Paul Walmsley

On Mon, 17 Feb 2020 00:32:23 PST (-0800), zong.li@sifive.com wrote:
> After the text section be mask as non-writable, the ftrace have to
> change the permission of text for dynamic patching the intructions.
> Add ftrace_arch_code_modify_prepare and
> ftrace_arch_code_modify_post_process to change permission.
>
> Signed-off-by: Zong Li <zong.li@sifive.com>
> ---
>  arch/riscv/kernel/ftrace.c | 18 ++++++++++++++++++
>  1 file changed, 18 insertions(+)
>
> diff --git a/arch/riscv/kernel/ftrace.c b/arch/riscv/kernel/ftrace.c
> index c40fdcdeb950..576df0807200 100644
> --- a/arch/riscv/kernel/ftrace.c
> +++ b/arch/riscv/kernel/ftrace.c
> @@ -7,9 +7,27 @@
>
>  #include <linux/ftrace.h>
>  #include <linux/uaccess.h>
> +#include <linux/memory.h>
> +#include <asm/set_memory.h>
>  #include <asm/cacheflush.h>
>
>  #ifdef CONFIG_DYNAMIC_FTRACE
> +int ftrace_arch_code_modify_prepare(void) __acquires(&text_mutex)
> +{
> +	mutex_lock(&text_mutex);
> +	set_kernel_text_rw();
> +	set_all_modules_text_rw();
> +	return 0;
> +}

None of the other architectures are doing anything remotely like this in these
functions, despite many supporting STRICT_KERNEL_RWX.  Having a function that
maps all text as RW seems super dangerous, as one stack attack means NX is
gone.

Looks like FIX_TEXT_POKE0 is the magic that makes the other ports work.

> +
> +int ftrace_arch_code_modify_post_process(void) __releases(&text_mutex)
> +{
> +	set_all_modules_text_ro();
> +	set_kernel_text_ro();
> +	mutex_unlock(&text_mutex);
> +	return 0;
> +}

Presumably this needs a icache flush as well?  Probably better to do so when
installing the instructions, though.

> +
>  static int ftrace_check_current_call(unsigned long hook_pos,
>  				     unsigned int *expected)
>  {


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 4/8] riscv: move exception table immediately after RO_DATA
  2020-03-05  0:57   ` Palmer Dabbelt
@ 2020-03-05  4:01     ` Zong Li
  0 siblings, 0 replies; 22+ messages in thread
From: Zong Li @ 2020-03-05  4:01 UTC (permalink / raw)
  To: Palmer Dabbelt
  Cc: linux-riscv, Albert Ou, Linux Kernel Mailing List, Zong Li,
	Paul Walmsley

Palmer Dabbelt <palmer@dabbelt.com> 於 2020年3月5日 週四 上午8:58寫道:
>
> On Mon, 17 Feb 2020 00:32:19 PST (-0800), zong.li@sifive.com wrote:
> > Move EXCEPTION_TABLE immediately after RO_DATA. Make it easy to set the
> > attribution of the sections which should be read-only at a time.
> > Move .sdata to indicate the start of data section with write permission.
> > This patch is prepared for STRICT_KERNEL_RWX support.
> >
> > Signed-off-by: Zong Li <zong.li@sifive.com>
> > ---
> >  arch/riscv/kernel/vmlinux.lds.S | 8 +++++---
> >  1 file changed, 5 insertions(+), 3 deletions(-)
> >
> > diff --git a/arch/riscv/kernel/vmlinux.lds.S b/arch/riscv/kernel/vmlinux.lds.S
> > index 1e0193ded420..4ba8a5397e8b 100644
> > --- a/arch/riscv/kernel/vmlinux.lds.S
> > +++ b/arch/riscv/kernel/vmlinux.lds.S
> > @@ -9,6 +9,7 @@
> >  #include <asm/page.h>
> >  #include <asm/cache.h>
> >  #include <asm/thread_info.h>
> > +#include <asm/set_memory.h>
> >
> >  OUTPUT_ARCH(riscv)
> >  ENTRY(_start)
> > @@ -52,12 +53,15 @@ SECTIONS
> >       }
> >
> >       /* Start of data section */
> > -     _sdata = .;
> >       RO_DATA(L1_CACHE_BYTES)
> >       .srodata : {
> >               *(.srodata*)
> >       }
> >
> > +     EXCEPTION_TABLE(0x10)
> > +
> > +     _sdata = .;
> > +
> >       RW_DATA(L1_CACHE_BYTES, PAGE_SIZE, THREAD_SIZE)
> >       .sdata : {
> >               __global_pointer$ = . + 0x800;
> > @@ -69,8 +73,6 @@ SECTIONS
> >
> >       BSS_SECTION(PAGE_SIZE, PAGE_SIZE, 0)
> >
> > -     EXCEPTION_TABLE(0x10)
> > -
> >       .rel.dyn : {
> >               *(.rel.dyn*)
> >       }
>
> As far as I can tell this is OK: core_kernel_data() explicitly says that RODATA
> may or may not be between _sdata and _edata.  That said, I think we should add
> __start_rodata and __end_rodata atomicly with this change (around RO_DATA and
> .srodata).
>

OK, I'll move _sdata back. Actually, here I need a symbol to specify
the start address at writable data (RW_DATA), thus, I could remove the
executable permission of .data section (from this symbol), and make
.rodata, .srodata and __ex_table read-only at a time (from
__start_rodata to this symbol). So even if we use __end_rodata to wrap
.srodata together with .rodata, exception table still be excluded, and
we have no idea where is the .data section start address. Do you think
it would be OK if we use _data to specify the start address at
writable data? If it's OK, whether we still need to add __end_rodata
after .srodata?


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 6/8] riscv: add STRICT_KERNEL_RWX support
  2020-03-05  1:21   ` Palmer Dabbelt
@ 2020-03-05  4:08     ` Zong Li
  0 siblings, 0 replies; 22+ messages in thread
From: Zong Li @ 2020-03-05  4:08 UTC (permalink / raw)
  To: Palmer Dabbelt
  Cc: linux-riscv, Albert Ou, Linux Kernel Mailing List, Zong Li,
	Paul Walmsley

Palmer Dabbelt <palmer@dabbelt.com> 於 2020年3月5日 週四 上午9:22寫道:
>
> On Mon, 17 Feb 2020 00:32:21 PST (-0800), zong.li@sifive.com wrote:
> > The commit contains that make text section as non-writable, rodata
> > section as read-only, and data section as non-executable.
> >
> > The init section should be changed to non-executable.
> >
> > Signed-off-by: Zong Li <zong.li@sifive.com>
> > ---
> >  arch/riscv/Kconfig                  |  1 +
> >  arch/riscv/include/asm/set_memory.h |  8 +++++
> >  arch/riscv/mm/init.c                | 45 +++++++++++++++++++++++++++++
> >  3 files changed, 54 insertions(+)
> >
> > diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
> > index f524d7e60648..308a4dbc0b39 100644
> > --- a/arch/riscv/Kconfig
> > +++ b/arch/riscv/Kconfig
> > @@ -62,6 +62,7 @@ config RISCV
> >       select ARCH_HAS_GIGANTIC_PAGE
> >       select ARCH_HAS_SET_DIRECT_MAP
> >       select ARCH_HAS_SET_MEMORY
> > +     select ARCH_HAS_STRICT_KERNEL_RWX
> >       select ARCH_WANT_HUGE_PMD_SHARE if 64BIT
> >       select SPARSEMEM_STATIC if 32BIT
> >       select ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT if MMU
> > diff --git a/arch/riscv/include/asm/set_memory.h b/arch/riscv/include/asm/set_memory.h
> > index a91f192063c2..d3076087cb34 100644
> > --- a/arch/riscv/include/asm/set_memory.h
> > +++ b/arch/riscv/include/asm/set_memory.h
> > @@ -15,6 +15,14 @@ int set_memory_rw(unsigned long addr, int numpages);
> >  int set_memory_x(unsigned long addr, int numpages);
> >  int set_memory_nx(unsigned long addr, int numpages);
> >
> > +#ifdef CONFIG_STRICT_KERNEL_RWX
> > +void set_kernel_text_ro(void);
> > +void set_kernel_text_rw(void);
> > +#else
> > +static inline void set_kernel_text_ro(void) { }
> > +static inline void set_kernel_text_rw(void) { }
> > +#endif
> > +
> >  int set_direct_map_invalid_noflush(struct page *page);
> >  int set_direct_map_default_noflush(struct page *page);
> >
> > diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c
> > index 965a8cf4829c..09fa643e079c 100644
> > --- a/arch/riscv/mm/init.c
> > +++ b/arch/riscv/mm/init.c
> > @@ -12,11 +12,13 @@
> >  #include <linux/sizes.h>
> >  #include <linux/of_fdt.h>
> >  #include <linux/libfdt.h>
> > +#include <linux/set_memory.h>
> >
> >  #include <asm/fixmap.h>
> >  #include <asm/tlbflush.h>
> >  #include <asm/sections.h>
> >  #include <asm/pgtable.h>
> > +#include <asm/ptdump.h>
> >  #include <asm/io.h>
> >
> >  #include "../kernel/head.h"
> > @@ -477,6 +479,49 @@ static void __init setup_vm_final(void)
> >       csr_write(CSR_SATP, PFN_DOWN(__pa_symbol(swapper_pg_dir)) | SATP_MODE);
> >       local_flush_tlb_all();
> >  }
> > +
> > +#ifdef CONFIG_STRICT_KERNEL_RWX
> > +void set_kernel_text_rw(void)
> > +{
> > +     unsigned long text_start = (unsigned long)_text;
> > +     unsigned long text_end = (unsigned long)_etext;
> > +
> > +     set_memory_rw(text_start, (text_end - text_start) >> PAGE_SHIFT);
> > +}
> > +
> > +void set_kernel_text_ro(void)
> > +{
> > +     unsigned long text_start = (unsigned long)_text;
> > +     unsigned long text_end = (unsigned long)_etext;
> > +
> > +     set_memory_ro(text_start, (text_end - text_start) >> PAGE_SHIFT);
> > +}
> > +
> > +void mark_rodata_ro(void)
> > +{
> > +     unsigned long text_start = (unsigned long)_text;
> > +     unsigned long text_end = (unsigned long)_etext;
> > +     unsigned long rodata_start = (unsigned long)__start_rodata;
> > +     unsigned long data_start = (unsigned long)_sdata;
> > +     unsigned long max_low = (unsigned long)(__va(PFN_PHYS(max_low_pfn)));
> > +
> > +     set_memory_ro(text_start, (text_end - text_start) >> PAGE_SHIFT);
> > +     set_memory_ro(rodata_start, (data_start - rodata_start) >> PAGE_SHIFT);
> > +     set_memory_nx(rodata_start, (data_start - rodata_start) >> PAGE_SHIFT);
>
> Ya, this'll risk barfing because of srodata.

It might be OK because the range includes .rodata, .srodata and
__ex_table sections, but I need another symbol instead of _sdata as
you mentioned in other patch.

>
> > +     set_memory_nx(data_start, (max_low - data_start) >> PAGE_SHIFT);
> > +}
> > +#endif
> > +
> > +void free_initmem(void)
> > +{
> > +     unsigned long init_begin = (unsigned long)__init_begin;
> > +     unsigned long init_end = (unsigned long)__init_end;
> > +
> > +     /* Make the region as non-execuatble. */
> > +     set_memory_nx(init_begin, (init_end - init_begin) >> PAGE_SHIFT);
> > +     free_initmem_default(POISON_FREE_INITMEM);
> > +}
> > +
> >  #else
> >  asmlinkage void __init setup_vm(uintptr_t dtb_pa)
> >  {
>


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 8/8] riscv: add two hook functions of ftrace
  2020-03-05  1:44   ` Palmer Dabbelt
@ 2020-03-05  4:27     ` Zong Li
  0 siblings, 0 replies; 22+ messages in thread
From: Zong Li @ 2020-03-05  4:27 UTC (permalink / raw)
  To: Palmer Dabbelt
  Cc: linux-riscv, Albert Ou, Linux Kernel Mailing List, Zong Li,
	Paul Walmsley

Palmer Dabbelt <palmer@dabbelt.com> 於 2020年3月5日 週四 上午9:44寫道:
>
> On Mon, 17 Feb 2020 00:32:23 PST (-0800), zong.li@sifive.com wrote:
> > After the text section be mask as non-writable, the ftrace have to
> > change the permission of text for dynamic patching the intructions.
> > Add ftrace_arch_code_modify_prepare and
> > ftrace_arch_code_modify_post_process to change permission.
> >
> > Signed-off-by: Zong Li <zong.li@sifive.com>
> > ---
> >  arch/riscv/kernel/ftrace.c | 18 ++++++++++++++++++
> >  1 file changed, 18 insertions(+)
> >
> > diff --git a/arch/riscv/kernel/ftrace.c b/arch/riscv/kernel/ftrace.c
> > index c40fdcdeb950..576df0807200 100644
> > --- a/arch/riscv/kernel/ftrace.c
> > +++ b/arch/riscv/kernel/ftrace.c
> > @@ -7,9 +7,27 @@
> >
> >  #include <linux/ftrace.h>
> >  #include <linux/uaccess.h>
> > +#include <linux/memory.h>
> > +#include <asm/set_memory.h>
> >  #include <asm/cacheflush.h>
> >
> >  #ifdef CONFIG_DYNAMIC_FTRACE
> > +int ftrace_arch_code_modify_prepare(void) __acquires(&text_mutex)
> > +{
> > +     mutex_lock(&text_mutex);
> > +     set_kernel_text_rw();
> > +     set_all_modules_text_rw();
> > +     return 0;
> > +}
>
> None of the other architectures are doing anything remotely like this in these
> functions, despite many supporting STRICT_KERNEL_RWX.  Having a function that
> maps all text as RW seems super dangerous, as one stack attack means NX is
> gone.
>
> Looks like FIX_TEXT_POKE0 is the magic that makes the other ports work.
>

Your concern is right. Let me change the way.

> > +
> > +int ftrace_arch_code_modify_post_process(void) __releases(&text_mutex)
> > +{
> > +     set_all_modules_text_ro();
> > +     set_kernel_text_ro();
> > +     mutex_unlock(&text_mutex);
> > +     return 0;
> > +}
>
> Presumably this needs a icache flush as well?  Probably better to do so when
> installing the instructions, though.
>

Yes, I think I lost it. Thanks.

> > +
> >  static int ftrace_check_current_call(unsigned long hook_pos,
> >                                    unsigned int *expected)
> >  {
>


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 7/8] riscv: add DEBUG_WX support
  2020-03-05  1:44   ` Palmer Dabbelt
@ 2020-03-05  5:53     ` Zong Li
  0 siblings, 0 replies; 22+ messages in thread
From: Zong Li @ 2020-03-05  5:53 UTC (permalink / raw)
  To: Palmer Dabbelt
  Cc: linux-riscv, Albert Ou, Linux Kernel Mailing List, Zong Li,
	Paul Walmsley

Palmer Dabbelt <palmer@dabbelt.com> 於 2020年3月5日 週四 上午9:44寫道:
>
> On Mon, 17 Feb 2020 00:32:22 PST (-0800), zong.li@sifive.com wrote:
> > Support DEBUG_WX to check whether there are mapping with write and
> > execute permission at the same time.
> >
> > Signed-off-by: Zong Li <zong.li@sifive.com>
> > ---
> >  arch/riscv/Kconfig.debug        | 30 ++++++++++++++++++++++++++++++
> >  arch/riscv/include/asm/ptdump.h |  6 ++++++
> >  arch/riscv/mm/init.c            |  2 ++
> >  3 files changed, 38 insertions(+)
> >
> > diff --git a/arch/riscv/Kconfig.debug b/arch/riscv/Kconfig.debug
> > index e69de29bb2d1..2bcd88e75626 100644
> > --- a/arch/riscv/Kconfig.debug
> > +++ b/arch/riscv/Kconfig.debug
> > @@ -0,0 +1,30 @@
> > +# SPDX-License-Identifier: GPL-2.0-only
> > +
> > +config DEBUG_WX
> > +     bool "Warn on W+X mappings at boot"
> > +     select PTDUMP_CORE
> > +     help
> > +       Generate a warning if any W+X mappings are found at boot.
> > +
> > +       This is useful for discovering cases where the kernel is leaving
> > +       W+X mappings after applying NX, as such mappings are a security risk.
> > +       This check also includes UXN, which should be set on all kernel
> > +       mappings.
> > +
> > +       Look for a message in dmesg output like this:
> > +
> > +         riscv/mm: Checked W+X mappings: passed, no W+X pages found.
> > +
> > +       or like this, if the check failed:
> > +
> > +         riscv/mm: Checked W+X mappings: FAILED, <N> W+X pages found.
> > +
> > +       Note that even if the check fails, your kernel is possibly
> > +       still fine, as W+X mappings are not a security hole in
> > +       themselves, what they do is that they make the exploitation
> > +       of other unfixed kernel bugs easier.
> > +
> > +       There is no runtime or memory usage effect of this option
> > +       once the kernel has booted up - it's a one time check.
> > +
> > +       If in doubt, say "Y".
>
> It looks like this comes verbatim from the arm64 port, at least.  I think we
> should just refactor this to some sort of ARCH_HAS_DEBUG_WX so we can share the
> code.  I usually do this by adding the shared support, using it for RISC-V, and
> then converting the other ports over.
>

OK. It seems to be different work, maybe I could separate this patch
in next version. Thanks.

> > diff --git a/arch/riscv/include/asm/ptdump.h b/arch/riscv/include/asm/ptdump.h
> > index e29af7191909..eb2a1cc5f22c 100644
> > --- a/arch/riscv/include/asm/ptdump.h
> > +++ b/arch/riscv/include/asm/ptdump.h
> > @@ -8,4 +8,10 @@
> >
> >  void ptdump_check_wx(void);
> >
> > +#ifdef CONFIG_DEBUG_WX
> > +#define debug_checkwx() ptdump_check_wx()
> > +#else
> > +#define debug_checkwx() do { } while (0)
> > +#endif
> > +
> >  #endif /* _ASM_RISCV_PTDUMP_H */
> > diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c
> > index 09fa643e079c..a05d76e5fefe 100644
> > --- a/arch/riscv/mm/init.c
> > +++ b/arch/riscv/mm/init.c
> > @@ -509,6 +509,8 @@ void mark_rodata_ro(void)
> >       set_memory_ro(rodata_start, (data_start - rodata_start) >> PAGE_SHIFT);
> >       set_memory_nx(rodata_start, (data_start - rodata_start) >> PAGE_SHIFT);
> >       set_memory_nx(data_start, (max_low - data_start) >> PAGE_SHIFT);
> > +
> > +     debug_checkwx();
> >  }
> >  #endif
>


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 0/8] Support strict kernel memory permissions for security
  2020-02-17  8:32 [PATCH 0/8] Support strict kernel memory permissions for security Zong Li
                   ` (7 preceding siblings ...)
  2020-02-17  8:32 ` [PATCH 8/8] riscv: add two hook functions of ftrace Zong Li
@ 2020-03-05 15:55 ` Palmer Dabbelt
  8 siblings, 0 replies; 22+ messages in thread
From: Palmer Dabbelt @ 2020-03-05 15:55 UTC (permalink / raw)
  To: zong.li; +Cc: linux-riscv, aou, linux-kernel, zong.li, Paul Walmsley

On Mon, 17 Feb 2020 00:32:15 PST (-0800), zong.li@sifive.com wrote:
> The main purpose of this patch series is changing the kernel mapping permission
> , make sure that code is not writeable, data is not executable, and read-only
> data is neither writable nor executable.
>
> This patch series also supports the relevant implementations such as
> ARCH_HAS_SET_MEMORY, ARCH_HAS_SET_DIRECT_MAP,
> ARCH_SUPPORTS_DEBUG_PAGEALLOC and DEBUG_WX.
>
> Zong Li (8):
>   riscv: add ARCH_HAS_SET_MEMORY support
>   riscv: add ARCH_HAS_SET_DIRECT_MAP support
>   riscv: add ARCH_SUPPORTS_DEBUG_PAGEALLOC support
>   riscv: move exception table immediately after RO_DATA
>   riscv: add alignment for text, rodata and data sections
>   riscv: add STRICT_KERNEL_RWX support
>   riscv: add DEBUG_WX support
>   riscv: add two hook functions of ftrace
>
>  arch/riscv/Kconfig                  |   6 +
>  arch/riscv/Kconfig.debug            |  30 +++++
>  arch/riscv/include/asm/ptdump.h     |   6 +
>  arch/riscv/include/asm/set_memory.h |  41 ++++++
>  arch/riscv/kernel/ftrace.c          |  18 +++
>  arch/riscv/kernel/vmlinux.lds.S     |  12 +-
>  arch/riscv/mm/Makefile              |   1 +
>  arch/riscv/mm/init.c                |  47 +++++++
>  arch/riscv/mm/pageattr.c            | 187 ++++++++++++++++++++++++++++
>  9 files changed, 344 insertions(+), 4 deletions(-)
>  create mode 100644 arch/riscv/include/asm/set_memory.h
>  create mode 100644 arch/riscv/mm/pageattr.c

Sorry, I had to run last night without quite finishing the patch set.  Just so
we're on the same page: there's some issues with the patch set, I'm assuming
you're submitting a v2 so I'm dropping this from my inbox.

Thanks!


^ permalink raw reply	[flat|nested] 22+ messages in thread

end of thread, other threads:[~2020-03-05 15:55 UTC | newest]

Thread overview: 22+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-02-17  8:32 [PATCH 0/8] Support strict kernel memory permissions for security Zong Li
2020-02-17  8:32 ` [PATCH 1/8] riscv: add ARCH_HAS_SET_MEMORY support Zong Li
2020-03-05  0:57   ` Palmer Dabbelt
2020-02-17  8:32 ` [PATCH 2/8] riscv: add ARCH_HAS_SET_DIRECT_MAP support Zong Li
2020-03-05  0:57   ` Palmer Dabbelt
2020-02-17  8:32 ` [PATCH 3/8] riscv: add ARCH_SUPPORTS_DEBUG_PAGEALLOC support Zong Li
2020-03-05  0:57   ` Palmer Dabbelt
2020-02-17  8:32 ` [PATCH 4/8] riscv: move exception table immediately after RO_DATA Zong Li
2020-03-05  0:57   ` Palmer Dabbelt
2020-03-05  4:01     ` Zong Li
2020-02-17  8:32 ` [PATCH 5/8] riscv: add alignment for text, rodata and data sections Zong Li
2020-03-05  0:58   ` Palmer Dabbelt
2020-02-17  8:32 ` [PATCH 6/8] riscv: add STRICT_KERNEL_RWX support Zong Li
2020-03-05  1:21   ` Palmer Dabbelt
2020-03-05  4:08     ` Zong Li
2020-02-17  8:32 ` [PATCH 7/8] riscv: add DEBUG_WX support Zong Li
2020-03-05  1:44   ` Palmer Dabbelt
2020-03-05  5:53     ` Zong Li
2020-02-17  8:32 ` [PATCH 8/8] riscv: add two hook functions of ftrace Zong Li
2020-03-05  1:44   ` Palmer Dabbelt
2020-03-05  4:27     ` Zong Li
2020-03-05 15:55 ` [PATCH 0/8] Support strict kernel memory permissions for security Palmer Dabbelt

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).