Messages in this thread Patch in this message |  | | From | Davidlohr Bueso <> | | Subject | [PATCH] riscv/futex: Bound number of LL/SC retries in cmpxchg | | Date | Tue, 5 May 2026 01:58:35 -0700 |
| |
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@stgolabs.net> --- Compile tested only.
arch/riscv/include/asm/futex.h | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-)
diff --git a/arch/riscv/include/asm/futex.h b/arch/riscv/include/asm/futex.h index 90c86b115e00..865701807014 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) @@ -77,6 +79,7 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, u32 oldval, u32 newval) { int ret = 0; + unsigned int loops = FUTEX_MAX_LOOPS; u32 val; uintptr_t tmp; @@ -85,16 +88,20 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, __enable_user_access(); __asm__ __volatile__ ( - "1: lr.w %[v],%[u] \n" + "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
|  |