diff options
| author | Alexandre Ghiti <alexghiti@rivosinc.com> | 2023-12-14 10:19:26 +0100 |
|---|---|---|
| committer | Palmer Dabbelt <palmer@rivosinc.com> | 2024-01-09 10:58:59 -0800 |
| commit | 420370f3ae3d3b883813fd3051a38805160b2b9f (patch) | |
| tree | 637445e78c14c045aa880edaf6c8994b7e8540e8 /arch/riscv/kernel/patch.c | |
| parent | ed5b7cfd7839f9280a63365c1133482b42d0981f (diff) | |
| download | linux-420370f3ae3d3b883813fd3051a38805160b2b9f.tar.gz linux-420370f3ae3d3b883813fd3051a38805160b2b9f.tar.bz2 linux-420370f3ae3d3b883813fd3051a38805160b2b9f.zip | |
riscv: Check if the code to patch lies in the exit section
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>
Diffstat (limited to 'arch/riscv/kernel/patch.c')
| -rw-r--r-- | arch/riscv/kernel/patch.c | 11 |
1 files changed, 10 insertions, 1 deletions
diff --git a/arch/riscv/kernel/patch.c b/arch/riscv/kernel/patch.c index 13ee7bf589a1..37e87fdcf6a0 100644 --- a/arch/riscv/kernel/patch.c +++ b/arch/riscv/kernel/patch.c @@ -14,6 +14,7 @@ #include <asm/fixmap.h> #include <asm/ftrace.h> #include <asm/patch.h> +#include <asm/sections.h> struct patch_insn { void *addr; @@ -25,6 +26,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". @@ -35,7 +44,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); |
