Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'riscv-for-linus-5.17-rc8' of git://git.kernel.org/pub/scm/linux/kernel/git/riscv/linux

Pull RISC-V fixes from Palmer Dabbelt:

- prevent users from enabling the alternatives framework (and thus
errata handling) on XIP kernels, where runtime code patching does not
function correctly.

- properly detect offset overflow for AUIPC-based relocations in
modules. This may manifest as modules calling arbitrary invalid
addresses, depending on the address allocated when a module is
loaded.

* tag 'riscv-for-linus-5.17-rc8' of git://git.kernel.org/pub/scm/linux/kernel/git/riscv/linux:
riscv: Fix auipc+jalr relocation range checks
riscv: alternative only works on !XIP_KERNEL

+19 -7
+1
arch/riscv/Kconfig.erratas
··· 2 2 3 3 config RISCV_ERRATA_ALTERNATIVE 4 4 bool "RISC-V alternative scheme" 5 + depends on !XIP_KERNEL 5 6 default y 6 7 help 7 8 This Kconfig allows the kernel to automatically patch the
+2 -2
arch/riscv/Kconfig.socs
··· 14 14 select CLK_SIFIVE 15 15 select CLK_SIFIVE_PRCI 16 16 select SIFIVE_PLIC 17 - select RISCV_ERRATA_ALTERNATIVE 18 - select ERRATA_SIFIVE 17 + select RISCV_ERRATA_ALTERNATIVE if !XIP_KERNEL 18 + select ERRATA_SIFIVE if !XIP_KERNEL 19 19 help 20 20 This enables support for SiFive SoC platform hardware. 21 21
+16 -5
arch/riscv/kernel/module.c
··· 13 13 #include <linux/pgtable.h> 14 14 #include <asm/sections.h> 15 15 16 + /* 17 + * The auipc+jalr instruction pair can reach any PC-relative offset 18 + * in the range [-2^31 - 2^11, 2^31 - 2^11) 19 + */ 20 + static bool riscv_insn_valid_32bit_offset(ptrdiff_t val) 21 + { 22 + #ifdef CONFIG_32BIT 23 + return true; 24 + #else 25 + return (-(1L << 31) - (1L << 11)) <= val && val < ((1L << 31) - (1L << 11)); 26 + #endif 27 + } 28 + 16 29 static int apply_r_riscv_32_rela(struct module *me, u32 *location, Elf_Addr v) 17 30 { 18 31 if (v != (u32)v) { ··· 108 95 ptrdiff_t offset = (void *)v - (void *)location; 109 96 s32 hi20; 110 97 111 - if (offset != (s32)offset) { 98 + if (!riscv_insn_valid_32bit_offset(offset)) { 112 99 pr_err( 113 100 "%s: target %016llx can not be addressed by the 32-bit offset from PC = %p\n", 114 101 me->name, (long long)v, location); ··· 210 197 Elf_Addr v) 211 198 { 212 199 ptrdiff_t offset = (void *)v - (void *)location; 213 - s32 fill_v = offset; 214 200 u32 hi20, lo12; 215 201 216 - if (offset != fill_v) { 202 + if (!riscv_insn_valid_32bit_offset(offset)) { 217 203 /* Only emit the plt entry if offset over 32-bit range */ 218 204 if (IS_ENABLED(CONFIG_MODULE_SECTIONS)) { 219 205 offset = module_emit_plt_entry(me, v); ··· 236 224 Elf_Addr v) 237 225 { 238 226 ptrdiff_t offset = (void *)v - (void *)location; 239 - s32 fill_v = offset; 240 227 u32 hi20, lo12; 241 228 242 - if (offset != fill_v) { 229 + if (!riscv_insn_valid_32bit_offset(offset)) { 243 230 pr_err( 244 231 "%s: target %016llx can not be addressed by the 32-bit offset from PC = %p\n", 245 232 me->name, (long long)v, location);