Skip to content

Commit 77fe1ba

Browse files
committed
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
2 parents 878409e + 0966d38 commit 77fe1ba

File tree

3 files changed

+19
-7
lines changed

3 files changed

+19
-7
lines changed

arch/riscv/Kconfig.erratas

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ menu "CPU errata selection"
22

33
config RISCV_ERRATA_ALTERNATIVE
44
bool "RISC-V alternative scheme"
5+
depends on !XIP_KERNEL
56
default y
67
help
78
This Kconfig allows the kernel to automatically patch the

arch/riscv/Kconfig.socs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ config SOC_SIFIVE
1414
select CLK_SIFIVE
1515
select CLK_SIFIVE_PRCI
1616
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
1919
help
2020
This enables support for SiFive SoC platform hardware.
2121

arch/riscv/kernel/module.c

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,19 @@
1313
#include <linux/pgtable.h>
1414
#include <asm/sections.h>
1515

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+
1629
static int apply_r_riscv_32_rela(struct module *me, u32 *location, Elf_Addr v)
1730
{
1831
if (v != (u32)v) {
@@ -95,7 +108,7 @@ static int apply_r_riscv_pcrel_hi20_rela(struct module *me, u32 *location,
95108
ptrdiff_t offset = (void *)v - (void *)location;
96109
s32 hi20;
97110

98-
if (offset != (s32)offset) {
111+
if (!riscv_insn_valid_32bit_offset(offset)) {
99112
pr_err(
100113
"%s: target %016llx can not be addressed by the 32-bit offset from PC = %p\n",
101114
me->name, (long long)v, location);
@@ -197,10 +210,9 @@ static int apply_r_riscv_call_plt_rela(struct module *me, u32 *location,
197210
Elf_Addr v)
198211
{
199212
ptrdiff_t offset = (void *)v - (void *)location;
200-
s32 fill_v = offset;
201213
u32 hi20, lo12;
202214

203-
if (offset != fill_v) {
215+
if (!riscv_insn_valid_32bit_offset(offset)) {
204216
/* Only emit the plt entry if offset over 32-bit range */
205217
if (IS_ENABLED(CONFIG_MODULE_SECTIONS)) {
206218
offset = module_emit_plt_entry(me, v);
@@ -224,10 +236,9 @@ static int apply_r_riscv_call_rela(struct module *me, u32 *location,
224236
Elf_Addr v)
225237
{
226238
ptrdiff_t offset = (void *)v - (void *)location;
227-
s32 fill_v = offset;
228239
u32 hi20, lo12;
229240

230-
if (offset != fill_v) {
241+
if (!riscv_insn_valid_32bit_offset(offset)) {
231242
pr_err(
232243
"%s: target %016llx can not be addressed by the 32-bit offset from PC = %p\n",
233244
me->name, (long long)v, location);

0 commit comments

Comments
 (0)