From: Fangyu Yu machine_kexec_prepare() calls set_memory_x() on the per-image control_code_page so the relocate stub copied into it can be executed during a normal kexec. machine_kexec_cleanup() is empty, so when the image is freed (via kexec -u, or because a later step in load failed) the page is returned to the buddy allocator with its executable bit still set. Once the page is reallocated for arbitrary kernel data, the W^X invariant is broken: a writable page also marked executable. Implement the architecture cleanup hook to call set_memory_nx() on the control code page for non-crash images, mirroring the set_memory_x() in prepare(). The crash path does not call set_memory_x() (the crash kernel is loaded into the reserved crashkernel region whose pages are not in the buddy allocator) and so does not need the cleanup. Fixes: fba8a8674f68 ("RISC-V: Add kexec support") Signed-off-by: Fangyu Yu --- arch/riscv/kernel/machine_kexec.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/arch/riscv/kernel/machine_kexec.c b/arch/riscv/kernel/machine_kexec.c index 2306ce3e5f22..ea6794c9f4c2 100644 --- a/arch/riscv/kernel/machine_kexec.c +++ b/arch/riscv/kernel/machine_kexec.c @@ -91,6 +91,19 @@ machine_kexec_prepare(struct kimage *image) void machine_kexec_cleanup(struct kimage *image) { + void *control_code_buffer; + + if (image->type == KEXEC_TYPE_CRASH || !image->control_code_page) + return; + + /* + * machine_kexec_prepare() called set_memory_x() on the control + * code page for non-crash images. Revert it before kimage_free() + * returns the page to the buddy allocator, so we do not leak an + * executable page back into general allocation. + */ + control_code_buffer = page_address(image->control_code_page); + set_memory_nx((unsigned long)control_code_buffer, 1); } -- 2.50.1