|
@@ -115,6 +115,9 @@ struct futex_q {
|
|
|
/* rt_waiter storage for requeue_pi: */
|
|
|
struct rt_mutex_waiter *rt_waiter;
|
|
|
|
|
|
+ /* The expected requeue pi target futex key: */
|
|
|
+ union futex_key *requeue_pi_key;
|
|
|
+
|
|
|
/* Bitset for the optional bitmasked wakeup */
|
|
|
u32 bitset;
|
|
|
};
|
|
@@ -1080,6 +1083,10 @@ static int futex_proxy_trylock_atomic(u32 __user *pifutex,
|
|
|
if (!top_waiter)
|
|
|
return 0;
|
|
|
|
|
|
+ /* Ensure we requeue to the expected futex. */
|
|
|
+ if (!match_futex(top_waiter->requeue_pi_key, key2))
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
/*
|
|
|
* Try to take the lock for top_waiter. Set the FUTEX_WAITERS bit in
|
|
|
* the contended case or if set_waiters is 1. The pi_state is returned
|
|
@@ -1260,6 +1267,12 @@ retry_private:
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
+ /* Ensure we requeue to the expected futex for requeue_pi. */
|
|
|
+ if (requeue_pi && !match_futex(this->requeue_pi_key, &key2)) {
|
|
|
+ ret = -EINVAL;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
/*
|
|
|
* Requeue nr_requeue waiters and possibly one more in the case
|
|
|
* of requeue_pi if we couldn't acquire the lock atomically.
|
|
@@ -1735,6 +1748,7 @@ static int futex_wait(u32 __user *uaddr, int fshared,
|
|
|
q.pi_state = NULL;
|
|
|
q.bitset = bitset;
|
|
|
q.rt_waiter = NULL;
|
|
|
+ q.requeue_pi_key = NULL;
|
|
|
|
|
|
if (abs_time) {
|
|
|
to = &timeout;
|
|
@@ -1842,6 +1856,7 @@ static int futex_lock_pi(u32 __user *uaddr, int fshared,
|
|
|
|
|
|
q.pi_state = NULL;
|
|
|
q.rt_waiter = NULL;
|
|
|
+ q.requeue_pi_key = NULL;
|
|
|
retry:
|
|
|
q.key = FUTEX_KEY_INIT;
|
|
|
ret = get_futex_key(uaddr, fshared, &q.key, VERIFY_WRITE);
|
|
@@ -2153,15 +2168,16 @@ static int futex_wait_requeue_pi(u32 __user *uaddr, int fshared,
|
|
|
debug_rt_mutex_init_waiter(&rt_waiter);
|
|
|
rt_waiter.task = NULL;
|
|
|
|
|
|
- q.pi_state = NULL;
|
|
|
- q.bitset = bitset;
|
|
|
- q.rt_waiter = &rt_waiter;
|
|
|
-
|
|
|
key2 = FUTEX_KEY_INIT;
|
|
|
ret = get_futex_key(uaddr2, fshared, &key2, VERIFY_WRITE);
|
|
|
if (unlikely(ret != 0))
|
|
|
goto out;
|
|
|
|
|
|
+ q.pi_state = NULL;
|
|
|
+ q.bitset = bitset;
|
|
|
+ q.rt_waiter = &rt_waiter;
|
|
|
+ q.requeue_pi_key = &key2;
|
|
|
+
|
|
|
/* Prepare to wait on uaddr. */
|
|
|
ret = futex_wait_setup(uaddr, val, fshared, &q, &hb);
|
|
|
if (ret)
|