Messages in this thread Patch in this message | | | From | Björn Töpel <> | Subject | [PATCH v2] riscv: mm: Proper page permissions after initmem free | Date | Tue, 15 Nov 2022 10:06:40 +0100 |
| |
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); } base-commit: 22dce2b89d6043d5c3f68384285fff5506109317 -- 2.37.2
| |