[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