summaryrefslogtreecommitdiffstats
path: root/arch/riscv/kernel
diff options
context:
space:
mode:
authorAtish Patra <atish.patra@wdc.com>2020-11-04 16:04:38 -0800
committerPalmer Dabbelt <palmerdabbelt@google.com>2020-11-25 16:05:28 -0800
commit19a00869028f4a28a36f90649166631dff6e3ccd (patch)
treeef4a68e11c94a44d7e9de3f6f83fe57877739ba9 /arch/riscv/kernel
parentb6566dc1acca38ce6ed845ce8a270fb181ff6d41 (diff)
downloadlinux-19a00869028f4a28a36f90649166631dff6e3ccd.tar.gz
linux-19a00869028f4a28a36f90649166631dff6e3ccd.tar.bz2
linux-19a00869028f4a28a36f90649166631dff6e3ccd.zip
RISC-V: Protect all kernel sections including init early
Currently, .init.text & .init.data are intermixed which makes it impossible apply different permissions to them. .init.data shouldn't need exec permissions while .init.text shouldn't have write permission. Moreover, the strict permission are only enforced /init starts. This leaves the kernel vulnerable from possible buggy built-in modules. Keep .init.text & .data in separate sections so that different permissions are applied to each section. Apply permissions to individual sections as early as possible. This improves the kernel protection under CONFIG_STRICT_KERNEL_RWX. We also need to restore the permissions for the entire _init section after it is freed so that those pages can be used for other purpose. Signed-off-by: Atish Patra <atish.patra@wdc.com> Tested-by: Greentime Hu <greentime.hu@sifive.com> Signed-off-by: Palmer Dabbelt <palmerdabbelt@google.com>
Diffstat (limited to 'arch/riscv/kernel')
-rw-r--r--arch/riscv/kernel/setup.c12
-rw-r--r--arch/riscv/kernel/vmlinux.lds.S49
2 files changed, 39 insertions, 22 deletions
diff --git a/arch/riscv/kernel/setup.c b/arch/riscv/kernel/setup.c
index 20470e5a7d3c..a834deab31d3 100644
--- a/arch/riscv/kernel/setup.c
+++ b/arch/riscv/kernel/setup.c
@@ -24,6 +24,7 @@
#include <asm/cpu_ops.h>
#include <asm/early_ioremap.h>
#include <asm/setup.h>
+#include <asm/set_memory.h>
#include <asm/sections.h>
#include <asm/sbi.h>
#include <asm/tlbflush.h>
@@ -252,6 +253,8 @@ void __init setup_arch(char **cmdline_p)
if (IS_ENABLED(CONFIG_RISCV_SBI))
sbi_init();
+ if (IS_ENABLED(CONFIG_STRICT_KERNEL_RWX))
+ protect_kernel_text_data();
#ifdef CONFIG_SWIOTLB
swiotlb_init(1);
#endif
@@ -281,3 +284,12 @@ static int __init topology_init(void)
return 0;
}
subsys_initcall(topology_init);
+
+void free_initmem(void)
+{
+ unsigned long init_begin = (unsigned long)__init_begin;
+ unsigned long init_end = (unsigned long)__init_end;
+
+ set_memory_rw_nx(init_begin, (init_end - init_begin) >> PAGE_SHIFT);
+ free_initmem_default(POISON_FREE_INITMEM);
+}
diff --git a/arch/riscv/kernel/vmlinux.lds.S b/arch/riscv/kernel/vmlinux.lds.S
index cacd7898ba7f..ca19ee5acd0a 100644
--- a/arch/riscv/kernel/vmlinux.lds.S
+++ b/arch/riscv/kernel/vmlinux.lds.S
@@ -29,6 +29,22 @@ SECTIONS
HEAD_TEXT_SECTION
. = ALIGN(PAGE_SIZE);
+ .text : {
+ _text = .;
+ _stext = .;
+ TEXT_TEXT
+ SCHED_TEXT
+ CPUIDLE_TEXT
+ LOCK_TEXT
+ KPROBES_TEXT
+ ENTRY_TEXT
+ IRQENTRY_TEXT
+ SOFTIRQENTRY_TEXT
+ *(.fixup)
+ _etext = .;
+ }
+
+ . = ALIGN(SECTION_ALIGN);
__init_begin = .;
__init_text_begin = .;
.init.text : AT(ADDR(.init.text) - LOAD_OFFSET) ALIGN(SECTION_ALIGN) { \
@@ -53,35 +69,24 @@ SECTIONS
{
EXIT_TEXT
}
- .exit.data :
- {
- EXIT_DATA
- }
- PERCPU_SECTION(L1_CACHE_BYTES)
- __init_end = .;
+ __init_text_end = .;
. = ALIGN(SECTION_ALIGN);
- .text : {
- _text = .;
- _stext = .;
- TEXT_TEXT
- SCHED_TEXT
- CPUIDLE_TEXT
- LOCK_TEXT
- KPROBES_TEXT
- ENTRY_TEXT
- IRQENTRY_TEXT
- SOFTIRQENTRY_TEXT
- *(.fixup)
- _etext = .;
- }
-
#ifdef CONFIG_EFI
. = ALIGN(PECOFF_SECTION_ALIGNMENT);
__pecoff_text_end = .;
#endif
-
+ /* Start of init data section */
+ __init_data_begin = .;
INIT_DATA_SECTION(16)
+ .exit.data :
+ {
+ EXIT_DATA
+ }
+ PERCPU_SECTION(L1_CACHE_BYTES)
+
+ __init_data_end = .;
+ __init_end = .;
/* Start of data section */
_sdata = .;