Skip to content

Commit 210d36d

Browse files
Davidlohr BuesoThomas Gleixner
authored andcommitted
futex: Clear stale exiting pointer in futex_lock_pi() retry path
Fuzzying/stressing futexes triggered: WARNING: kernel/futex/core.c:825 at wait_for_owner_exiting+0x7a/0x80, CPU#11: futex_lock_pi_s/524 When futex_lock_pi_atomic() sees the owner is exiting, it returns -EBUSY and stores a refcounted task pointer in 'exiting'. After wait_for_owner_exiting() consumes that reference, the local pointer is never reset to nil. Upon a retry, if futex_lock_pi_atomic() returns a different error, the bogus pointer is passed to wait_for_owner_exiting(). CPU0 CPU1 CPU2 futex_lock_pi(uaddr) // acquires the PI futex exit() futex_cleanup_begin() futex_state = EXITING; futex_lock_pi(uaddr) futex_lock_pi_atomic() attach_to_pi_owner() // observes EXITING *exiting = owner; // takes ref return -EBUSY wait_for_owner_exiting(-EBUSY, owner) put_task_struct(); // drops ref // exiting still points to owner goto retry; futex_lock_pi_atomic() lock_pi_update_atomic() cmpxchg(uaddr) *uaddr ^= WAITERS // whatever // value changed return -EAGAIN; wait_for_owner_exiting(-EAGAIN, exiting) // stale WARN_ON_ONCE(exiting) Fix this by resetting upon retry, essentially aligning it with requeue_pi. Fixes: 3ef240e ("futex: Prevent exit livelock") Signed-off-by: Davidlohr Bueso <dave@stgolabs.net> Signed-off-by: Thomas Gleixner <tglx@kernel.org> Cc: stable@vger.kernel.org Link: https://patch.msgid.link/20260326001759.4129680-1-dave@stgolabs.net
1 parent 190a8c4 commit 210d36d

1 file changed

Lines changed: 2 additions & 1 deletion

File tree

kernel/futex/pi.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -918,7 +918,7 @@ int fixup_pi_owner(u32 __user *uaddr, struct futex_q *q, int locked)
918918
int futex_lock_pi(u32 __user *uaddr, unsigned int flags, ktime_t *time, int trylock)
919919
{
920920
struct hrtimer_sleeper timeout, *to;
921-
struct task_struct *exiting = NULL;
921+
struct task_struct *exiting;
922922
struct rt_mutex_waiter rt_waiter;
923923
struct futex_q q = futex_q_init;
924924
DEFINE_WAKE_Q(wake_q);
@@ -933,6 +933,7 @@ int futex_lock_pi(u32 __user *uaddr, unsigned int flags, ktime_t *time, int tryl
933933
to = futex_setup_timer(time, &timeout, flags, 0);
934934

935935
retry:
936+
exiting = NULL;
936937
ret = get_futex_key(uaddr, flags, &q.key, FUTEX_WRITE);
937938
if (unlikely(ret != 0))
938939
goto out;

0 commit comments

Comments
 (0)