]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
riscv: Check if the code to patch lies in the exit section
authorAlexandre Ghiti <alexghiti@rivosinc.com>
Thu, 14 Dec 2023 09:19:26 +0000 (10:19 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 25 Jan 2024 23:27:45 +0000 (15:27 -0800)
[ Upstream commit 420370f3ae3d3b883813fd3051a38805160b2b9f ]

Otherwise we fall through to vmalloc_to_page() which panics since the
address does not lie in the vmalloc region.

Fixes: 043cb41a85de ("riscv: introduce interfaces to patch kernel code")
Signed-off-by: Alexandre Ghiti <alexghiti@rivosinc.com>
Reviewed-by: Charlie Jenkins <charlie@rivosinc.com>
Link: https://lore.kernel.org/r/20231214091926.203439-1-alexghiti@rivosinc.com
Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
arch/riscv/include/asm/sections.h
arch/riscv/kernel/patch.c
arch/riscv/kernel/vmlinux-xip.lds.S
arch/riscv/kernel/vmlinux.lds.S

index 32336e8a17cb071dce1acfd70e8f00e1765d3d05..a393d5035c54330874c49ca982f641f13c53c02e 100644 (file)
@@ -13,6 +13,7 @@ extern char _start_kernel[];
 extern char __init_data_begin[], __init_data_end[];
 extern char __init_text_begin[], __init_text_end[];
 extern char __alt_start[], __alt_end[];
+extern char __exittext_begin[], __exittext_end[];
 
 static inline bool is_va_kernel_text(uintptr_t va)
 {
index e099961453cca26eaff54b31b2575676fc36b476..160e5c1caa9c4007612f763e4cf55843d3f56ba1 100644 (file)
@@ -13,6 +13,7 @@
 #include <asm/fixmap.h>
 #include <asm/ftrace.h>
 #include <asm/patch.h>
+#include <asm/sections.h>
 
 struct patch_insn {
        void *addr;
@@ -23,6 +24,14 @@ struct patch_insn {
 int riscv_patch_in_stop_machine = false;
 
 #ifdef CONFIG_MMU
+
+static inline bool is_kernel_exittext(uintptr_t addr)
+{
+       return system_state < SYSTEM_RUNNING &&
+               addr >= (uintptr_t)__exittext_begin &&
+               addr < (uintptr_t)__exittext_end;
+}
+
 /*
  * The fix_to_virt(, idx) needs a const value (not a dynamic variable of
  * reg-a0) or BUILD_BUG_ON failed with "idx >= __end_of_fixed_addresses".
@@ -33,7 +42,7 @@ static __always_inline void *patch_map(void *addr, const unsigned int fixmap)
        uintptr_t uintaddr = (uintptr_t) addr;
        struct page *page;
 
-       if (core_kernel_text(uintaddr))
+       if (core_kernel_text(uintaddr) || is_kernel_exittext(uintaddr))
                page = phys_to_page(__pa_symbol(addr));
        else if (IS_ENABLED(CONFIG_STRICT_MODULE_RWX))
                page = vmalloc_to_page(addr);
index 75e0fa8a700ae62c92ddce41a572b7876a0f24ed..24a2fdd3be6a06c58bb1d7580489e18d76c2fa1a 100644 (file)
@@ -29,10 +29,12 @@ SECTIONS
        HEAD_TEXT_SECTION
        INIT_TEXT_SECTION(PAGE_SIZE)
        /* we have to discard exit text and such at runtime, not link time */
+       __exittext_begin = .;
        .exit.text :
        {
                EXIT_TEXT
        }
+       __exittext_end = .;
 
        .text : {
                _text = .;
index 4e6c88aa4d87049c9bba77c0379491e2a5ae222f..d478e063b8785d00ea4e0170122a9b39a13ea8d0 100644 (file)
@@ -72,10 +72,12 @@ SECTIONS
                __soc_builtin_dtb_table_end = .;
        }
        /* we have to discard exit text and such at runtime, not link time */
+       __exittext_begin = .;
        .exit.text :
        {
                EXIT_TEXT
        }
+       __exittext_end = .;
 
        __init_text_end = .;
        . = ALIGN(SECTION_ALIGN);