riscv: add STRICT_KERNEL_RWX support
authorZong Li <zong.li@sifive.com>
Mon, 9 Mar 2020 16:55:41 +0000 (00:55 +0800)
committerPalmer Dabbelt <palmerdabbelt@google.com>
Thu, 26 Mar 2020 16:24:45 +0000 (09:24 -0700)
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>
Signed-off-by: Palmer Dabbelt <palmerdabbelt@google.com>
arch/riscv/Kconfig
arch/riscv/include/asm/set_memory.h
arch/riscv/mm/init.c

index 31fbc6e..dfc9c3e 100644 (file)
@@ -61,6 +61,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
index 4c5bae7..c38df47 100644 (file)
@@ -22,6 +22,14 @@ static inline int set_memory_x(unsigned long addr, int numpages) { return 0; }
 static inline int set_memory_nx(unsigned long addr, int numpages) { return 0; }
 #endif
 
+#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);
 
index 965a8cf..0c625a5 100644 (file)
@@ -12,6 +12,7 @@
 #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>
@@ -477,6 +478,17 @@ static void __init setup_vm_final(void)
        csr_write(CSR_SATP, PFN_DOWN(__pa_symbol(swapper_pg_dir)) | SATP_MODE);
        local_flush_tlb_all();
 }
+
+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)
 {
@@ -488,6 +500,38 @@ static inline void setup_vm_final(void)
 }
 #endif /* CONFIG_MMU */
 
+#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)_data;
+       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 __init paging_init(void)
 {
        setup_vm_final();