Messages in this thread | | | Date | Tue, 15 Nov 2022 15:53:47 +0100 | Subject | Re: [PATCH v2] riscv: mm: Proper page permissions after initmem free | From | Alexandre Ghiti <> |
| |
Hi Björn,
On 15/11/2022 10:06, Björn Töpel wrote: > From: Björn Töpel <bjorn@rivosinc.com> > > 64-bit RISC-V kernels have the kernel image mapped separately to alias > the linear map. The linear map and the kernel image map are documented > as "direct mapping" and "kernel" respectively in [1]. > > At image load time, the linear map corresponding to the kernel image > is set to PAGE_READ permission, and the kernel image map is set to > PAGE_READ|PAGE_EXEC. > > When the initmem is freed, the pages in the linear map should be > restored to PAGE_READ|PAGE_WRITE, whereas the corresponding pages in > the kernel image map should be restored to PAGE_READ, by removing the > PAGE_EXEC permission. > > This is not the case. For 64-bit kernels, only the linear map is > restored to its proper page permissions at initmem free, and not the > kernel image map. > > In practise this results in that the kernel can potentially jump to > dead __init code, and start executing invalid instructions, without > getting an exception. > > Restore the freed initmem properly, by setting both the kernel image > map to the correct permissions. > > [1] Documentation/riscv/vm-layout.rst > > Fixes: e5c35fa04019 ("riscv: Map the kernel with correct permissions the first time") > Signed-off-by: Björn Töpel <bjorn@rivosinc.com> > --- > v2: * Do not set the kernel image map to PAGE_WRITE. (Alex) > * Massaged the commit message a bit. > > Samuel, I removed your Reviewed-by:/Tested-by: for the v2. > --- > arch/riscv/kernel/setup.c | 9 +++++---- > 1 file changed, 5 insertions(+), 4 deletions(-) > > diff --git a/arch/riscv/kernel/setup.c b/arch/riscv/kernel/setup.c > index 67ec1fadcfe2..86acd690d529 100644 > --- a/arch/riscv/kernel/setup.c > +++ b/arch/riscv/kernel/setup.c > @@ -322,10 +322,11 @@ subsys_initcall(topology_init); > > void free_initmem(void) > { > - if (IS_ENABLED(CONFIG_STRICT_KERNEL_RWX)) > - set_kernel_memory(lm_alias(__init_begin), lm_alias(__init_end), > - IS_ENABLED(CONFIG_64BIT) ? > - set_memory_rw : set_memory_rw_nx); > + if (IS_ENABLED(CONFIG_STRICT_KERNEL_RWX)) { > + set_kernel_memory(lm_alias(__init_begin), lm_alias(__init_end), set_memory_rw_nx); > + if (IS_ENABLED(CONFIG_64BIT)) > + set_kernel_memory(__init_begin, __init_end, set_memory_nx); > + } > > free_initmem_default(POISON_FREE_INITMEM); > }
This looks good to me, I tested it on both defconfig and rv32_defconfig on qemu, so you can add:
Reviewed-by: Alexandre Ghiti <alex@ghiti.fr> Tested-by: Alexandre Ghiti <alex@ghiti.fr>
Thanks,
Alex
> base-commit: 22dce2b89d6043d5c3f68384285fff5506109317
| |