Message ID | 20201026230254.911912-4-atish.patra@wdc.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | Improve kernel section protections | expand |
On Mon, Oct 26, 2020 at 04:02:51PM -0700, Atish Patra wrote: > Currently, all memblocks are mapped with PAGE_KERNEL_EXEC and the strict > permissions are only enforced after /init starts. This leaves the kernel > vulnerable from possible buggy built-in modules. > > Apply permissions to individual sections as early as possible. > > Signed-off-by: Atish Patra <atish.patra@wdc.com> > --- > arch/riscv/include/asm/set_memory.h | 2 ++ > arch/riscv/kernel/setup.c | 2 ++ > arch/riscv/mm/init.c | 11 +++++++++-- > 3 files changed, 13 insertions(+), 2 deletions(-) > > diff --git a/arch/riscv/include/asm/set_memory.h b/arch/riscv/include/asm/set_memory.h > index 4c5bae7ca01c..4cc3a4e2afd3 100644 > --- a/arch/riscv/include/asm/set_memory.h > +++ b/arch/riscv/include/asm/set_memory.h > @@ -15,11 +15,13 @@ 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); > +void protect_kernel_text_data(void); > #else > static inline int set_memory_ro(unsigned long addr, int numpages) { return 0; } > static inline int set_memory_rw(unsigned long addr, int numpages) { return 0; } > 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; } > +static inline void protect_kernel_text_data(void) {}; > #endif > > int set_direct_map_invalid_noflush(struct page *page); > diff --git a/arch/riscv/kernel/setup.c b/arch/riscv/kernel/setup.c > index 7d6a04ae3929..b722c5bf892c 100644 > --- a/arch/riscv/kernel/setup.c > +++ b/arch/riscv/kernel/setup.c > @@ -22,6 +22,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> > @@ -92,6 +93,7 @@ void __init setup_arch(char **cmdline_p) > #if IS_ENABLED(CONFIG_RISCV_SBI) > sbi_init(); > #endif > + protect_kernel_text_data(); > #ifdef CONFIG_SWIOTLB > swiotlb_init(1); > #endif > diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c > index ea933b789a88..5f196f8158d4 100644 > --- a/arch/riscv/mm/init.c > +++ b/arch/riscv/mm/init.c > @@ -608,7 +608,7 @@ static inline void setup_vm_final(void) > #endif /* CONFIG_MMU */ > > #ifdef CONFIG_STRICT_KERNEL_RWX > -void mark_rodata_ro(void) > +void protect_kernel_text_data(void) > { > unsigned long text_start = (unsigned long)_text; > unsigned long text_end = (unsigned long)_etext; > @@ -617,9 +617,16 @@ void mark_rodata_ro(void) > unsigned long max_low = (unsigned long)(__va(PFN_PHYS(max_low_pfn))); > A comment about that rodata permissions are set later would be nice here. > 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); > +} > + > +void mark_rodata_ro(void) > +{ > + unsigned long rodata_start = (unsigned long)__start_rodata; > + unsigned long data_start = (unsigned long)_data; > + > + set_memory_ro(rodata_start, (data_start - rodata_start) >> PAGE_SHIFT); > > debug_checkwx(); > } > -- > 2.25.1 >
On Tue, Oct 27, 2020 at 3:01 AM Mike Rapoport <rppt@kernel.org> wrote: > > On Mon, Oct 26, 2020 at 04:02:51PM -0700, Atish Patra wrote: > > Currently, all memblocks are mapped with PAGE_KERNEL_EXEC and the strict > > permissions are only enforced after /init starts. This leaves the kernel > > vulnerable from possible buggy built-in modules. > > > > Apply permissions to individual sections as early as possible. > > > > Signed-off-by: Atish Patra <atish.patra@wdc.com> > > --- > > arch/riscv/include/asm/set_memory.h | 2 ++ > > arch/riscv/kernel/setup.c | 2 ++ > > arch/riscv/mm/init.c | 11 +++++++++-- > > 3 files changed, 13 insertions(+), 2 deletions(-) > > > > diff --git a/arch/riscv/include/asm/set_memory.h b/arch/riscv/include/asm/set_memory.h > > index 4c5bae7ca01c..4cc3a4e2afd3 100644 > > --- a/arch/riscv/include/asm/set_memory.h > > +++ b/arch/riscv/include/asm/set_memory.h > > @@ -15,11 +15,13 @@ 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); > > +void protect_kernel_text_data(void); > > #else > > static inline int set_memory_ro(unsigned long addr, int numpages) { return 0; } > > static inline int set_memory_rw(unsigned long addr, int numpages) { return 0; } > > 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; } > > +static inline void protect_kernel_text_data(void) {}; > > #endif > > > > int set_direct_map_invalid_noflush(struct page *page); > > diff --git a/arch/riscv/kernel/setup.c b/arch/riscv/kernel/setup.c > > index 7d6a04ae3929..b722c5bf892c 100644 > > --- a/arch/riscv/kernel/setup.c > > +++ b/arch/riscv/kernel/setup.c > > @@ -22,6 +22,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> > > @@ -92,6 +93,7 @@ void __init setup_arch(char **cmdline_p) > > #if IS_ENABLED(CONFIG_RISCV_SBI) > > sbi_init(); > > #endif > > + protect_kernel_text_data(); > > #ifdef CONFIG_SWIOTLB > > swiotlb_init(1); > > #endif > > diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c > > index ea933b789a88..5f196f8158d4 100644 > > --- a/arch/riscv/mm/init.c > > +++ b/arch/riscv/mm/init.c > > @@ -608,7 +608,7 @@ static inline void setup_vm_final(void) > > #endif /* CONFIG_MMU */ > > > > #ifdef CONFIG_STRICT_KERNEL_RWX > > -void mark_rodata_ro(void) > > +void protect_kernel_text_data(void) > > { > > unsigned long text_start = (unsigned long)_text; > > unsigned long text_end = (unsigned long)_etext; > > @@ -617,9 +617,16 @@ void mark_rodata_ro(void) > > unsigned long max_low = (unsigned long)(__va(PFN_PHYS(max_low_pfn))); > > > > A comment about that rodata permissions are set later would be nice > here. > Sure. I will add that. > > 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); > > +} > > + > > +void mark_rodata_ro(void) > > +{ > > + unsigned long rodata_start = (unsigned long)__start_rodata; > > + unsigned long data_start = (unsigned long)_data; > > + > > + set_memory_ro(rodata_start, (data_start - rodata_start) >> PAGE_SHIFT); > > > > debug_checkwx(); > > } > > -- > > 2.25.1 > > > > -- > Sincerely yours, > Mike. > > _______________________________________________ > linux-riscv mailing list > linux-riscv@lists.infradead.org > http://lists.infradead.org/mailman/listinfo/linux-riscv
diff --git a/arch/riscv/include/asm/set_memory.h b/arch/riscv/include/asm/set_memory.h index 4c5bae7ca01c..4cc3a4e2afd3 100644 --- a/arch/riscv/include/asm/set_memory.h +++ b/arch/riscv/include/asm/set_memory.h @@ -15,11 +15,13 @@ 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); +void protect_kernel_text_data(void); #else static inline int set_memory_ro(unsigned long addr, int numpages) { return 0; } static inline int set_memory_rw(unsigned long addr, int numpages) { return 0; } 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; } +static inline void protect_kernel_text_data(void) {}; #endif int set_direct_map_invalid_noflush(struct page *page); diff --git a/arch/riscv/kernel/setup.c b/arch/riscv/kernel/setup.c index 7d6a04ae3929..b722c5bf892c 100644 --- a/arch/riscv/kernel/setup.c +++ b/arch/riscv/kernel/setup.c @@ -22,6 +22,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> @@ -92,6 +93,7 @@ void __init setup_arch(char **cmdline_p) #if IS_ENABLED(CONFIG_RISCV_SBI) sbi_init(); #endif + protect_kernel_text_data(); #ifdef CONFIG_SWIOTLB swiotlb_init(1); #endif diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c index ea933b789a88..5f196f8158d4 100644 --- a/arch/riscv/mm/init.c +++ b/arch/riscv/mm/init.c @@ -608,7 +608,7 @@ static inline void setup_vm_final(void) #endif /* CONFIG_MMU */ #ifdef CONFIG_STRICT_KERNEL_RWX -void mark_rodata_ro(void) +void protect_kernel_text_data(void) { unsigned long text_start = (unsigned long)_text; unsigned long text_end = (unsigned long)_etext; @@ -617,9 +617,16 @@ void mark_rodata_ro(void) 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); +} + +void mark_rodata_ro(void) +{ + unsigned long rodata_start = (unsigned long)__start_rodata; + unsigned long data_start = (unsigned long)_data; + + set_memory_ro(rodata_start, (data_start - rodata_start) >> PAGE_SHIFT); debug_checkwx(); }
Currently, all memblocks are mapped with PAGE_KERNEL_EXEC and the strict permissions are only enforced after /init starts. This leaves the kernel vulnerable from possible buggy built-in modules. Apply permissions to individual sections as early as possible. Signed-off-by: Atish Patra <atish.patra@wdc.com> --- arch/riscv/include/asm/set_memory.h | 2 ++ arch/riscv/kernel/setup.c | 2 ++ arch/riscv/mm/init.c | 11 +++++++++-- 3 files changed, 13 insertions(+), 2 deletions(-)