Fuzzying/stressing futexes triggered:
WARNING: kernel/futex/core.c:825 at oh_my_futex+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()
// sees 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 with requeue_pi.
Fixes: 3ef240eaff36 ("futex: Prevent exit livelock")
Signed-off-by: Davidlohr Bueso <dave@stgolabs.net>
---
kernel/futex/pi.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/kernel/futex/pi.c b/kernel/futex/pi.c
index 49ab5f40e86c..643199fdbe62 100644
--- a/kernel/futex/pi.c
+++ b/kernel/futex/pi.c
@@ -923,7 +923,7 @@ int fixup_pi_owner(u32 __user *uaddr, struct futex_q *q, int locked)
int futex_lock_pi(u32 __user *uaddr, unsigned int flags, ktime_t *time, int trylock)
{
struct hrtimer_sleeper timeout, *to;
- struct task_struct *exiting = NULL;
+ struct task_struct *exiting;
struct rt_mutex_waiter rt_waiter;
struct futex_q q = futex_q_init;
DEFINE_WAKE_Q(wake_q);
@@ -938,6 +938,7 @@ int futex_lock_pi(u32 __user *uaddr, unsigned int flags, ktime_t *time, int tryl
to = futex_setup_timer(time, &timeout, flags, 0);
retry:
+ exiting = NULL;
ret = get_futex_key(uaddr, flags, &q.key, FUTEX_WRITE);
if (unlikely(ret != 0))
goto out;
--
2.39.5