[PATCH v2 2/6] riscv: insn: Set sstatus.MXR when reading userspace instruction
Yicong Yang
yang.yicong at picoheart.com
Tue Jul 28 02:46:23 PDT 2026
The __read_insn() uses get_user() to read userspace instructions.
Bo Gan noticed that get_user() is insufficient in this case since
it's possible for the instruction segment mapped as execute-only
and get_user() doesn't have permissions to load it. The architecture
provides sstatus.MXR for handling this so set MXR when reading
userspace instruction.
Cc: Bo Gan <ganboing at gmail.com>
Signed-off-by: Yicong Yang <yang.yicong at picoheart.com>
---
arch/riscv/include/asm/csr.h | 1 +
arch/riscv/include/asm/insn.h | 2 ++
arch/riscv/include/asm/processor.h | 2 +-
arch/riscv/kernel/asm-offsets.c | 6 +++---
arch/riscv/kernel/entry.S | 14 +++++++-------
5 files changed, 14 insertions(+), 11 deletions(-)
diff --git a/arch/riscv/include/asm/csr.h b/arch/riscv/include/asm/csr.h
index d5d309b3b570..7bfbda958f0f 100644
--- a/arch/riscv/include/asm/csr.h
+++ b/arch/riscv/include/asm/csr.h
@@ -17,6 +17,7 @@
#define SR_SPP _AC(0x00000100, UL) /* Previously Supervisor */
#define SR_MPP _AC(0x00001800, UL) /* Previously Machine */
#define SR_SUM _AC(0x00040000, UL) /* Supervisor User Memory Access */
+#define SR_MXR _AC(0x00080000, UL) /* Make eXecutable Readable */
/* zicfilp landing pad status bit */
#define SR_SPELP _AC(0x00800000, UL)
diff --git a/arch/riscv/include/asm/insn.h b/arch/riscv/include/asm/insn.h
index 5f60367c2abc..c36d1dfa16c6 100644
--- a/arch/riscv/include/asm/insn.h
+++ b/arch/riscv/include/asm/insn.h
@@ -606,7 +606,9 @@ static inline void riscv_insn_insert_utype_itype_imm(u32 *utype_insn, u32 *itype
int __ret; \
\
if (user_mode(regs)) { \
+ csr_set(CSR_STATUS, SR_MXR); \
__ret = get_user(insn, (type __user *) insn_addr); \
+ csr_clear(CSR_STATUS, SR_MXR); \
} else { \
insn = *(type *)insn_addr; \
__ret = 0; \
diff --git a/arch/riscv/include/asm/processor.h b/arch/riscv/include/asm/processor.h
index 812517b2cec1..1e1523952b45 100644
--- a/arch/riscv/include/asm/processor.h
+++ b/arch/riscv/include/asm/processor.h
@@ -111,7 +111,7 @@ struct thread_struct {
struct __riscv_d_ext_state fstate;
unsigned long bad_cause;
unsigned long envcfg;
- unsigned long sum;
+ unsigned long sum_mxr;
u32 riscv_v_flags;
u32 vstate_ctrl;
struct __riscv_v_ext_state vstate;
diff --git a/arch/riscv/kernel/asm-offsets.c b/arch/riscv/kernel/asm-offsets.c
index a75f0cfea1e9..b6de2179570b 100644
--- a/arch/riscv/kernel/asm-offsets.c
+++ b/arch/riscv/kernel/asm-offsets.c
@@ -35,7 +35,7 @@ void asm_offsets(void)
OFFSET(TASK_THREAD_S9, task_struct, thread.s[9]);
OFFSET(TASK_THREAD_S10, task_struct, thread.s[10]);
OFFSET(TASK_THREAD_S11, task_struct, thread.s[11]);
- OFFSET(TASK_THREAD_SUM, task_struct, thread.sum);
+ OFFSET(TASK_THREAD_SUM_MXR, task_struct, thread.sum_mxr);
OFFSET(TASK_TI_CPU, task_struct, thread_info.cpu);
OFFSET(TASK_TI_PREEMPT_COUNT, task_struct, thread_info.preempt_count);
@@ -352,8 +352,8 @@ void asm_offsets(void)
offsetof(struct task_struct, thread.s[11])
- offsetof(struct task_struct, thread.ra)
);
- DEFINE(TASK_THREAD_SUM_RA,
- offsetof(struct task_struct, thread.sum)
+ DEFINE(TASK_THREAD_SUM_MXR_RA,
+ offsetof(struct task_struct, thread.sum_mxr)
- offsetof(struct task_struct, thread.ra)
);
diff --git a/arch/riscv/kernel/entry.S b/arch/riscv/kernel/entry.S
index d799c4e56f80..9ccc74aafece 100644
--- a/arch/riscv/kernel/entry.S
+++ b/arch/riscv/kernel/entry.S
@@ -172,13 +172,13 @@ SYM_CODE_START(handle_exception)
save_from_x6_to_x31
/*
- * Disable user-mode memory access as it should only be set in the
- * actual user copy routines.
+ * Disable user-mode memory access and MXR as it should only be set in
+ * the actual user copy routines.
*
* Disable the FPU/Vector to detect illegal usage of floating point
* or vector in kernel space.
*/
- li t0, SR_SUM | SR_FS_VS
+ li t0, SR_SUM | SR_MXR | SR_FS_VS
#ifdef CONFIG_64BIT
li t1, SR_ELP
or t0, t0, t1
@@ -443,15 +443,15 @@ SYM_FUNC_START(__switch_to)
REG_S s10, TASK_THREAD_S10_RA(a3)
REG_S s11, TASK_THREAD_S11_RA(a3)
- /* save the user space access flag */
+ /* save the user space access and MXR flag */
csrr s0, CSR_STATUS
- REG_S s0, TASK_THREAD_SUM_RA(a3)
+ REG_S s0, TASK_THREAD_SUM_MXR_RA(a3)
/* Save the kernel shadow call stack pointer */
scs_save_current
/* Restore context from next->thread */
- REG_L s0, TASK_THREAD_SUM_RA(a4)
- li s1, SR_SUM
+ REG_L s0, TASK_THREAD_SUM_MXR_RA(a4)
+ li s1, SR_SUM | SR_MXR
and s0, s0, s1
csrs CSR_STATUS, s0
REG_L ra, TASK_THREAD_RA_RA(a4)
--
2.50.1 (Apple Git-155)
More information about the linux-riscv
mailing list