futex: Validate waiter correctly in futex_proxy_trylock_atomic()
[linux-2.6-microblaze.git] / kernel / futex.c
index 2ecb075..a1f27fd 100644 (file)
@@ -179,7 +179,7 @@ struct futex_pi_state {
        /*
         * The PI object:
         */
-       struct rt_mutex pi_mutex;
+       struct rt_mutex_base pi_mutex;
 
        struct task_struct *owner;
        refcount_t refcount;
@@ -1493,11 +1493,11 @@ static void mark_wake_futex(struct wake_q_head *wake_q, struct futex_q *q)
  */
 static int wake_futex_pi(u32 __user *uaddr, u32 uval, struct futex_pi_state *pi_state)
 {
-       u32 curval, newval;
        struct rt_mutex_waiter *top_waiter;
        struct task_struct *new_owner;
        bool postunlock = false;
-       DEFINE_WAKE_Q(wake_q);
+       DEFINE_RT_WAKE_Q(wqh);
+       u32 curval, newval;
        int ret = 0;
 
        top_waiter = rt_mutex_top_waiter(&pi_state->pi_mutex);
@@ -1549,14 +1549,14 @@ static int wake_futex_pi(u32 __user *uaddr, u32 uval, struct futex_pi_state *pi_
                 * not fail.
                 */
                pi_state_update_owner(pi_state, new_owner);
-               postunlock = __rt_mutex_futex_unlock(&pi_state->pi_mutex, &wake_q);
+               postunlock = __rt_mutex_futex_unlock(&pi_state->pi_mutex, &wqh);
        }
 
 out_unlock:
        raw_spin_unlock_irq(&pi_state->pi_mutex.wait_lock);
 
        if (postunlock)
-               rt_mutex_postunlock(&wake_q);
+               rt_mutex_postunlock(&wqh);
 
        return ret;
 }
@@ -1879,6 +1879,13 @@ futex_proxy_trylock_atomic(u32 __user *pifutex, struct futex_hash_bucket *hb1,
        if (!top_waiter)
                return 0;
 
+       /*
+        * Ensure that this is a waiter sitting in futex_wait_requeue_pi()
+        * and waiting on the 'waitqueue' futex which is always !PI.
+        */
+       if (!top_waiter->rt_waiter || top_waiter->pi_state)
+               ret = -EINVAL;
+
        /* Ensure we requeue to the expected futex. */
        if (!match_futex(top_waiter->requeue_pi_key, key2))
                return -EINVAL;
@@ -3254,7 +3261,7 @@ static int futex_wait_requeue_pi(u32 __user *uaddr, unsigned int flags,
                        ret = ret < 0 ? ret : 0;
                }
        } else {
-               struct rt_mutex *pi_mutex;
+               struct rt_mutex_base *pi_mutex;
 
                /*
                 * We have been woken up by futex_unlock_pi(), a timeout, or a