[PATCH v2] riscv: cfi: Bounds check restore token in create_rstor_token() before swap

Tobias Klauser tklauser at distanz.ch
Tue Nov 10 03:11:57 PST 2026


create_rstor_token() computes addr and passes it to amo_user_shstk(),
which executes ssamoswap.d on it under __enable_user_access() without
ever validating that addr is a legitimate user-space address. The
sibling function restore_user_shstk() had the same issue and was fixed
by commit df333b72c0e1 ("riscv: cfi: Bounds check restore token before
swap").

Both callers of amo_user_shstk() need the same access_ok() check, so
move it into amo_user_shstk() itself to deduplicate it.

Fixes: c70772afd5cc ("riscv/mm: Implement map_shadow_stack() syscall")
Reviewed-by: Samuel Holland <samuel.holland at sifive.com>
Signed-off-by: Tobias Klauser <tklauser at distanz.ch>
---
v2: Moved the access_ok() check into amo_user_shstk(), per Samuel's
    feedback. Added his Reviewed-by. Link to v1:
    https://lore.kernel.org/linux-riscv/20261103132003.24312-1-tklauser@distanz.ch/

 arch/riscv/kernel/usercfi.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/riscv/kernel/usercfi.c b/arch/riscv/kernel/usercfi.c
index 86141e5bab82..dd6595322ee1 100644
--- a/arch/riscv/kernel/usercfi.c
+++ b/arch/riscv/kernel/usercfi.c
@@ -125,6 +125,9 @@ static noinline unsigned long amo_user_shstk(unsigned long __user *addr, unsigne
 	 */
 	unsigned long swap = -1;
 
+	if (!access_ok(addr, SHSTK_ENTRY_SIZE))
+		return -1;
+
 	__enable_user_access();
 	asm goto(".option push\n"
 		".option arch, +zicfiss\n"
@@ -200,9 +203,6 @@ int restore_user_shstk(struct task_struct *tsk, unsigned long shstk_ptr)
 	unsigned long __user *token_ptr = (unsigned long __user *)shstk_ptr;
 	unsigned long token = 0;
 
-	if (!access_ok(token_ptr, sizeof(token)))
-		return -EFAULT;
-
 	token = amo_user_shstk(token_ptr, 0);
 	if (token == -1)
 		return -EFAULT;
-- 
2.56.0




More information about the linux-riscv mailing list