Messages in this thread | | | Date | Tue, 27 Oct 2020 12:45:45 +0200 | From | Mike Rapoport <> | Subject | Re: [PATCH v2 5/6] RISC-V: Protect .init.text & .init.data |
| |
On Mon, Oct 26, 2020 at 04:02:53PM -0700, Atish Patra wrote: > 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. > > Keep them in separate sections so that different permissions are applied to > each section. 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> > --- > arch/riscv/include/asm/sections.h | 2 ++ > arch/riscv/include/asm/set_memory.h | 2 ++ > arch/riscv/kernel/setup.c | 9 +++++ > arch/riscv/kernel/vmlinux.lds.S | 51 ++++++++++++++++------------- > arch/riscv/mm/init.c | 8 ++++- > arch/riscv/mm/pageattr.c | 6 ++++ > 6 files changed, 54 insertions(+), 24 deletions(-) > > diff --git a/arch/riscv/include/asm/sections.h b/arch/riscv/include/asm/sections.h > index 3a9971b1210f..1595c5b60cfd 100644 > --- a/arch/riscv/include/asm/sections.h > +++ b/arch/riscv/include/asm/sections.h > @@ -9,5 +9,7 @@ > > extern char _start[]; > extern char _start_kernel[]; > +extern char __init_data_begin[], __init_data_end[]; > +extern char __init_text_begin[], __init_text_end[]; > > #endif /* __ASM_SECTIONS_H */ > diff --git a/arch/riscv/include/asm/set_memory.h b/arch/riscv/include/asm/set_memory.h > index 4cc3a4e2afd3..913429c9c1ae 100644 > --- a/arch/riscv/include/asm/set_memory.h > +++ b/arch/riscv/include/asm/set_memory.h > @@ -15,6 +15,7 @@ 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); > +int set_memory_default(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; } > @@ -22,6 +23,7 @@ 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) {}; > +static inline int set_memory_default(unsigned long addr, int numpages) { return 0; } > #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 b722c5bf892c..abfbdc8cfef3 100644 > --- a/arch/riscv/kernel/setup.c > +++ b/arch/riscv/kernel/setup.c > @@ -123,3 +123,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_default(init_begin, (init_end - init_begin) >> PAGE_SHIFT);
And what does "default" imply? Maybe set_memory_rw() would better name ...
> + free_initmem_default(POISON_FREE_INITMEM); > +}
...
> diff --git a/arch/riscv/mm/pageattr.c b/arch/riscv/mm/pageattr.c > index 19fecb362d81..04f3fc16aa9c 100644 > --- a/arch/riscv/mm/pageattr.c > +++ b/arch/riscv/mm/pageattr.c > @@ -128,6 +128,12 @@ static int __set_memory(unsigned long addr, int numpages, pgprot_t set_mask, > return ret; > } > > +int set_memory_default(unsigned long addr, int numpages) > +{ > + return __set_memory(addr, numpages, __pgprot(_PAGE_KERNEL), > + __pgprot(_PAGE_EXEC));
... because you'd need to find what _PAGE_KERNEL is, do bitwise ops and than find out that default is apparently RW :)
> +} > + > int set_memory_ro(unsigned long addr, int numpages) > { > return __set_memory(addr, numpages, __pgprot(_PAGE_READ), > -- > 2.25.1 >
-- Sincerely yours, Mike.
| |