[PATCH v2] riscv/futex: Bound number of LL/SC retries in cmpxchg

Davidlohr Bueso dave at stgolabs.net
Mon Jul 13 09:15:29 PDT 2026


ping?

On Tue, 05 May 2026, Davidlohr Bueso wrote:

>futex_atomic_cmpxchg_inatomic() does an unbounded LR/SC retry loop while
>(minimally) holding the hb lock + pf disabled. This can lead to pathological
>cases from unpriviledged userspace pi operations.
>
>Bound the retry loop to (arbitrarily) 128 iterations and bail: drop locks,
>rechedule and retry the operation, similar to the arm64 variant, as of
>03110a5cb216 ("arm64: futex: Bound number of LDXR/STXR loops in FUTEX_WAKE_OP").
>
>Signed-off-by: Davidlohr Bueso <dave at stgolabs.net>
>---
>v2: patch now applies (and removed a whitespace change).
>Compile tested only.
>
> arch/riscv/include/asm/futex.h | 14 +++++++++++---
> 1 file changed, 11 insertions(+), 3 deletions(-)
>
>diff --git a/arch/riscv/include/asm/futex.h b/arch/riscv/include/asm/futex.h
>index 90c86b115e00..be69d4211248 100644
>--- a/arch/riscv/include/asm/futex.h
>+++ b/arch/riscv/include/asm/futex.h
>@@ -13,6 +13,8 @@
> #include <asm/asm.h>
> #include <asm/asm-extable.h>
>
>+#define FUTEX_MAX_LOOPS 128
>+
> /* We don't even really need the extable code, but for now keep it simple */
> #ifndef CONFIG_MMU
> #define __enable_user_access()		do { } while (0)
>@@ -79,6 +81,7 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
>	int ret = 0;
>	u32 val;
>	uintptr_t tmp;
>+	unsigned int loops = FUTEX_MAX_LOOPS;
>
>	if (!access_ok(uaddr, sizeof(u32)))
>		return -EFAULT;
>@@ -88,12 +91,17 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
>	"1:	lr.w %[v],%[u]				\n"
>	"	bne %[v],%z[ov],3f			\n"
>	"2:	sc.w.aqrl %[t],%z[nv],%[u]		\n"
>-	"	bnez %[t],1b				\n"
>+	"	beqz %[t],3f				\n"
>+	"	addi %[lp],%[lp],-1			\n"
>+	"	bnez %[lp],1b				\n"
>+	"	li %[r],%[eagain]			\n"
>	"3:						\n"
>		_ASM_EXTABLE_UACCESS_ERR(1b, 3b, %[r])	\
>		_ASM_EXTABLE_UACCESS_ERR(2b, 3b, %[r])	\
>-	: [r] "+r" (ret), [v] "=&r" (val), [u] "+m" (*uaddr), [t] "=&r" (tmp)
>-	: [ov] "Jr" ((long)(int)oldval), [nv] "Jr" (newval)
>+	: [r] "+r" (ret), [v] "=&r" (val), [u] "+m" (*uaddr),
>+	  [t] "=&r" (tmp), [lp] "+r" (loops)
>+	: [ov] "Jr" ((long)(int)oldval), [nv] "Jr" (newval),
>+	  [eagain] "i" (-EAGAIN)
>	: "memory");
>	__disable_user_access();
>
>--
>2.39.5
>
>
>_______________________________________________
>linux-riscv mailing list
>linux-riscv at lists.infradead.org
>http://lists.infradead.org/mailman/listinfo/linux-riscv



More information about the linux-riscv mailing list