--- /dev/null
+From 13fbca4c6ecd96ec1a1cfa2e4f2ce191fe928a5e Mon Sep 17 00:00:00 2001
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Tue, 3 Jun 2014 12:27:07 +0000
+Subject: futex: Always cleanup owner tid in unlock_pi
+
+From: Thomas Gleixner <tglx@linutronix.de>
+
+commit 13fbca4c6ecd96ec1a1cfa2e4f2ce191fe928a5e upstream.
+
+If the owner died bit is set at futex_unlock_pi, we currently do not
+cleanup the user space futex. So the owner TID of the current owner
+(the unlocker) persists. That's observable inconsistant state,
+especially when the ownership of the pi state got transferred.
+
+Clean it up unconditionally.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Cc: Kees Cook <keescook@chromium.org>
+Cc: Will Drewry <wad@chromium.org>
+Cc: Darren Hart <dvhart@linux.intel.com>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ kernel/futex.c | 44 ++++++++++++++++++++------------------------
+ 1 file changed, 20 insertions(+), 24 deletions(-)
+
+--- a/kernel/futex.c
++++ b/kernel/futex.c
+@@ -903,6 +903,7 @@ static int wake_futex_pi(u32 __user *uad
+ struct task_struct *new_owner;
+ struct futex_pi_state *pi_state = this->pi_state;
+ u32 uninitialized_var(curval), newval;
++ int ret = 0;
+
+ if (!pi_state)
+ return -EINVAL;
+@@ -926,23 +927,19 @@ static int wake_futex_pi(u32 __user *uad
+ new_owner = this->task;
+
+ /*
+- * We pass it to the next owner. (The WAITERS bit is always
+- * kept enabled while there is PI state around. We must also
+- * preserve the owner died bit.)
+- */
+- if (!(uval & FUTEX_OWNER_DIED)) {
+- int ret = 0;
+-
+- newval = FUTEX_WAITERS | task_pid_vnr(new_owner);
+-
+- if (cmpxchg_futex_value_locked(&curval, uaddr, uval, newval))
+- ret = -EFAULT;
+- else if (curval != uval)
+- ret = -EINVAL;
+- if (ret) {
+- raw_spin_unlock(&pi_state->pi_mutex.wait_lock);
+- return ret;
+- }
++ * We pass it to the next owner. The WAITERS bit is always
++ * kept enabled while there is PI state around. We cleanup the
++ * owner died bit, because we are the owner.
++ */
++ newval = FUTEX_WAITERS | task_pid_vnr(new_owner);
++
++ if (cmpxchg_futex_value_locked(&curval, uaddr, uval, newval))
++ ret = -EFAULT;
++ else if (curval != uval)
++ ret = -EINVAL;
++ if (ret) {
++ raw_spin_unlock(&pi_state->pi_mutex.wait_lock);
++ return ret;
+ }
+
+ raw_spin_lock_irq(&pi_state->owner->pi_lock);
+@@ -2187,9 +2184,10 @@ retry:
+ /*
+ * To avoid races, try to do the TID -> 0 atomic transition
+ * again. If it succeeds then we can return without waking
+- * anyone else up:
++ * anyone else up. We only try this if neither the waiters nor
++ * the owner died bit are set.
+ */
+- if (!(uval & FUTEX_OWNER_DIED) &&
++ if (!(uval & ~FUTEX_TID_MASK) &&
+ cmpxchg_futex_value_locked(&uval, uaddr, vpid, 0))
+ goto pi_faulted;
+ /*
+@@ -2221,11 +2219,9 @@ retry:
+ /*
+ * No waiters - kernel unlocks the futex:
+ */
+- if (!(uval & FUTEX_OWNER_DIED)) {
+- ret = unlock_futex_pi(uaddr, uval);
+- if (ret == -EFAULT)
+- goto pi_faulted;
+- }
++ ret = unlock_futex_pi(uaddr, uval);
++ if (ret == -EFAULT)
++ goto pi_faulted;
+
+ out_unlock:
+ spin_unlock(&hb->lock);
--- /dev/null
+From 54a217887a7b658e2650c3feff22756ab80c7339 Mon Sep 17 00:00:00 2001
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Tue, 3 Jun 2014 12:27:08 +0000
+Subject: futex: Make lookup_pi_state more robust
+
+From: Thomas Gleixner <tglx@linutronix.de>
+
+commit 54a217887a7b658e2650c3feff22756ab80c7339 upstream.
+
+The current implementation of lookup_pi_state has ambigous handling of
+the TID value 0 in the user space futex. We can get into the kernel
+even if the TID value is 0, because either there is a stale waiters bit
+or the owner died bit is set or we are called from the requeue_pi path
+or from user space just for fun.
+
+The current code avoids an explicit sanity check for pid = 0 in case
+that kernel internal state (waiters) are found for the user space
+address. This can lead to state leakage and worse under some
+circumstances.
+
+Handle the cases explicit:
+
+ Waiter | pi_state | pi->owner | uTID | uODIED | ?
+
+ [1] NULL | --- | --- | 0 | 0/1 | Valid
+ [2] NULL | --- | --- | >0 | 0/1 | Valid
+
+ [3] Found | NULL | -- | Any | 0/1 | Invalid
+
+ [4] Found | Found | NULL | 0 | 1 | Valid
+ [5] Found | Found | NULL | >0 | 1 | Invalid
+
+ [6] Found | Found | task | 0 | 1 | Valid
+
+ [7] Found | Found | NULL | Any | 0 | Invalid
+
+ [8] Found | Found | task | ==taskTID | 0/1 | Valid
+ [9] Found | Found | task | 0 | 0 | Invalid
+ [10] Found | Found | task | !=taskTID | 0/1 | Invalid
+
+ [1] Indicates that the kernel can acquire the futex atomically. We
+ came came here due to a stale FUTEX_WAITERS/FUTEX_OWNER_DIED bit.
+
+ [2] Valid, if TID does not belong to a kernel thread. If no matching
+ thread is found then it indicates that the owner TID has died.
+
+ [3] Invalid. The waiter is queued on a non PI futex
+
+ [4] Valid state after exit_robust_list(), which sets the user space
+ value to FUTEX_WAITERS | FUTEX_OWNER_DIED.
+
+ [5] The user space value got manipulated between exit_robust_list()
+ and exit_pi_state_list()
+
+ [6] Valid state after exit_pi_state_list() which sets the new owner in
+ the pi_state but cannot access the user space value.
+
+ [7] pi_state->owner can only be NULL when the OWNER_DIED bit is set.
+
+ [8] Owner and user space value match
+
+ [9] There is no transient state which sets the user space TID to 0
+ except exit_robust_list(), but this is indicated by the
+ FUTEX_OWNER_DIED bit. See [4]
+
+[10] There is no transient state which leaves owner and user space
+ TID out of sync.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Cc: Kees Cook <keescook@chromium.org>
+Cc: Will Drewry <wad@chromium.org>
+Cc: Darren Hart <dvhart@linux.intel.com>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ kernel/futex.c | 134 +++++++++++++++++++++++++++++++++++++++++++++------------
+ 1 file changed, 106 insertions(+), 28 deletions(-)
+
+--- a/kernel/futex.c
++++ b/kernel/futex.c
+@@ -592,10 +592,58 @@ void exit_pi_state_list(struct task_stru
+ raw_spin_unlock_irq(&curr->pi_lock);
+ }
+
++/*
++ * We need to check the following states:
++ *
++ * Waiter | pi_state | pi->owner | uTID | uODIED | ?
++ *
++ * [1] NULL | --- | --- | 0 | 0/1 | Valid
++ * [2] NULL | --- | --- | >0 | 0/1 | Valid
++ *
++ * [3] Found | NULL | -- | Any | 0/1 | Invalid
++ *
++ * [4] Found | Found | NULL | 0 | 1 | Valid
++ * [5] Found | Found | NULL | >0 | 1 | Invalid
++ *
++ * [6] Found | Found | task | 0 | 1 | Valid
++ *
++ * [7] Found | Found | NULL | Any | 0 | Invalid
++ *
++ * [8] Found | Found | task | ==taskTID | 0/1 | Valid
++ * [9] Found | Found | task | 0 | 0 | Invalid
++ * [10] Found | Found | task | !=taskTID | 0/1 | Invalid
++ *
++ * [1] Indicates that the kernel can acquire the futex atomically. We
++ * came came here due to a stale FUTEX_WAITERS/FUTEX_OWNER_DIED bit.
++ *
++ * [2] Valid, if TID does not belong to a kernel thread. If no matching
++ * thread is found then it indicates that the owner TID has died.
++ *
++ * [3] Invalid. The waiter is queued on a non PI futex
++ *
++ * [4] Valid state after exit_robust_list(), which sets the user space
++ * value to FUTEX_WAITERS | FUTEX_OWNER_DIED.
++ *
++ * [5] The user space value got manipulated between exit_robust_list()
++ * and exit_pi_state_list()
++ *
++ * [6] Valid state after exit_pi_state_list() which sets the new owner in
++ * the pi_state but cannot access the user space value.
++ *
++ * [7] pi_state->owner can only be NULL when the OWNER_DIED bit is set.
++ *
++ * [8] Owner and user space value match
++ *
++ * [9] There is no transient state which sets the user space TID to 0
++ * except exit_robust_list(), but this is indicated by the
++ * FUTEX_OWNER_DIED bit. See [4]
++ *
++ * [10] There is no transient state which leaves owner and user space
++ * TID out of sync.
++ */
+ static int
+ lookup_pi_state(u32 uval, struct futex_hash_bucket *hb,
+- union futex_key *key, struct futex_pi_state **ps,
+- struct task_struct *task)
++ union futex_key *key, struct futex_pi_state **ps)
+ {
+ struct futex_pi_state *pi_state = NULL;
+ struct futex_q *this, *next;
+@@ -608,12 +656,13 @@ lookup_pi_state(u32 uval, struct futex_h
+ plist_for_each_entry_safe(this, next, head, list) {
+ if (match_futex(&this->key, key)) {
+ /*
+- * Another waiter already exists - bump up
+- * the refcount and return its pi_state:
++ * Sanity check the waiter before increasing
++ * the refcount and attaching to it.
+ */
+ pi_state = this->pi_state;
+ /*
+- * Userspace might have messed up non-PI and PI futexes
++ * Userspace might have messed up non-PI and
++ * PI futexes [3]
+ */
+ if (unlikely(!pi_state))
+ return -EINVAL;
+@@ -621,44 +670,70 @@ lookup_pi_state(u32 uval, struct futex_h
+ WARN_ON(!atomic_read(&pi_state->refcount));
+
+ /*
+- * When pi_state->owner is NULL then the owner died
+- * and another waiter is on the fly. pi_state->owner
+- * is fixed up by the task which acquires
+- * pi_state->rt_mutex.
+- *
+- * We do not check for pid == 0 which can happen when
+- * the owner died and robust_list_exit() cleared the
+- * TID.
++ * Handle the owner died case:
+ */
+- if (pid && pi_state->owner) {
++ if (uval & FUTEX_OWNER_DIED) {
+ /*
+- * Bail out if user space manipulated the
+- * futex value.
++ * exit_pi_state_list sets owner to NULL and
++ * wakes the topmost waiter. The task which
++ * acquires the pi_state->rt_mutex will fixup
++ * owner.
+ */
+- if (pid != task_pid_vnr(pi_state->owner))
++ if (!pi_state->owner) {
++ /*
++ * No pi state owner, but the user
++ * space TID is not 0. Inconsistent
++ * state. [5]
++ */
++ if (pid)
++ return -EINVAL;
++ /*
++ * Take a ref on the state and
++ * return. [4]
++ */
++ goto out_state;
++ }
++
++ /*
++ * If TID is 0, then either the dying owner
++ * has not yet executed exit_pi_state_list()
++ * or some waiter acquired the rtmutex in the
++ * pi state, but did not yet fixup the TID in
++ * user space.
++ *
++ * Take a ref on the state and return. [6]
++ */
++ if (!pid)
++ goto out_state;
++ } else {
++ /*
++ * If the owner died bit is not set,
++ * then the pi_state must have an
++ * owner. [7]
++ */
++ if (!pi_state->owner)
+ return -EINVAL;
+ }
+
+ /*
+- * Protect against a corrupted uval. If uval
+- * is 0x80000000 then pid is 0 and the waiter
+- * bit is set. So the deadlock check in the
+- * calling code has failed and we did not fall
+- * into the check above due to !pid.
++ * Bail out if user space manipulated the
++ * futex value. If pi state exists then the
++ * owner TID must be the same as the user
++ * space TID. [9/10]
+ */
+- if (task && pi_state->owner == task)
+- return -EDEADLK;
++ if (pid != task_pid_vnr(pi_state->owner))
++ return -EINVAL;
+
++ out_state:
+ atomic_inc(&pi_state->refcount);
+ *ps = pi_state;
+-
+ return 0;
+ }
+ }
+
+ /*
+ * We are the first waiter - try to look up the real owner and attach
+- * the new pi_state to it, but bail out when TID = 0
++ * the new pi_state to it, but bail out when TID = 0 [1]
+ */
+ if (!pid)
+ return -ESRCH;
+@@ -691,6 +766,9 @@ lookup_pi_state(u32 uval, struct futex_h
+ return ret;
+ }
+
++ /*
++ * No existing pi state. First waiter. [2]
++ */
+ pi_state = alloc_pi_state();
+
+ /*
+@@ -811,7 +889,7 @@ retry:
+ * We dont have the lock. Look up the PI state (or create it if
+ * we are the first waiter):
+ */
+- ret = lookup_pi_state(uval, hb, key, ps, task);
++ ret = lookup_pi_state(uval, hb, key, ps);
+
+ if (unlikely(ret)) {
+ switch (ret) {
+@@ -1414,7 +1492,7 @@ retry_private:
+ * rereading and handing potential crap to
+ * lookup_pi_state.
+ */
+- ret = lookup_pi_state(ret, hb2, &key2, &pi_state, NULL);
++ ret = lookup_pi_state(ret, hb2, &key2, &pi_state);
+ }
+
+ switch (ret) {
--- /dev/null
+From e9c243a5a6de0be8e584c604d353412584b592f8 Mon Sep 17 00:00:00 2001
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Tue, 3 Jun 2014 12:27:06 +0000
+Subject: futex-prevent-requeue-pi-on-same-futex.patch futex: Forbid uaddr == uaddr2 in futex_requeue(..., requeue_pi=1)
+
+From: Thomas Gleixner <tglx@linutronix.de>
+
+commit e9c243a5a6de0be8e584c604d353412584b592f8 upstream.
+
+If uaddr == uaddr2, then we have broken the rule of only requeueing from
+a non-pi futex to a pi futex with this call. If we attempt this, then
+dangling pointers may be left for rt_waiter resulting in an exploitable
+condition.
+
+This change brings futex_requeue() in line with futex_wait_requeue_pi()
+which performs the same check as per commit 6f7b0a2a5c0f ("futex: Forbid
+uaddr == uaddr2 in futex_wait_requeue_pi()")
+
+[ tglx: Compare the resulting keys as well, as uaddrs might be
+ different depending on the mapping ]
+
+Fixes CVE-2014-3153.
+
+Reported-by: Pinkie Pie
+Signed-off-by: Will Drewry <wad@chromium.org>
+Signed-off-by: Kees Cook <keescook@chromium.org>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Reviewed-by: Darren Hart <dvhart@linux.intel.com>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ kernel/futex.c | 25 +++++++++++++++++++++++++
+ 1 file changed, 25 insertions(+)
+
+--- a/kernel/futex.c
++++ b/kernel/futex.c
+@@ -1293,6 +1293,13 @@ static int futex_requeue(u32 __user *uad
+
+ if (requeue_pi) {
+ /*
++ * Requeue PI only works on two distinct uaddrs. This
++ * check is only valid for private futexes. See below.
++ */
++ if (uaddr1 == uaddr2)
++ return -EINVAL;
++
++ /*
+ * requeue_pi requires a pi_state, try to allocate it now
+ * without any locks in case it fails.
+ */
+@@ -1330,6 +1337,15 @@ retry:
+ if (unlikely(ret != 0))
+ goto out_put_key1;
+
++ /*
++ * The check above which compares uaddrs is not sufficient for
++ * shared futexes. We need to compare the keys:
++ */
++ if (requeue_pi && match_futex(&key1, &key2)) {
++ ret = -EINVAL;
++ goto out_put_keys;
++ }
++
+ hb1 = hash_futex(&key1);
+ hb2 = hash_futex(&key2);
+
+@@ -2360,6 +2376,15 @@ static int futex_wait_requeue_pi(u32 __u
+ if (ret)
+ goto out_key2;
+
++ /*
++ * The check above which compares uaddrs is not sufficient for
++ * shared futexes. We need to compare the keys:
++ */
++ if (match_futex(&q.key, &key2)) {
++ ret = -EINVAL;
++ goto out_put_keys;
++ }
++
+ /* Queue the futex_q, drop the hb lock, wait for wakeup. */
+ futex_wait_queue_me(hb, &q, to);
+
--- /dev/null
+From b3eaa9fc5cd0a4d74b18f6b8dc617aeaf1873270 Mon Sep 17 00:00:00 2001
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Tue, 3 Jun 2014 12:27:06 +0000
+Subject: futex: Validate atomic acquisition in futex_lock_pi_atomic()
+
+From: Thomas Gleixner <tglx@linutronix.de>
+
+commit b3eaa9fc5cd0a4d74b18f6b8dc617aeaf1873270 upstream.
+
+We need to protect the atomic acquisition in the kernel against rogue
+user space which sets the user space futex to 0, so the kernel side
+acquisition succeeds while there is existing state in the kernel
+associated to the real owner.
+
+Verify whether the futex has waiters associated with kernel state. If
+it has, return -EINVAL. The state is corrupted already, so no point in
+cleaning it up. Subsequent calls will fail as well. Not our problem.
+
+[ tglx: Use futex_top_waiter() and explain why we do not need to try
+ restoring the already corrupted user space state. ]
+
+Signed-off-by: Darren Hart <dvhart@linux.intel.com>
+Cc: Kees Cook <keescook@chromium.org>
+Cc: Will Drewry <wad@chromium.org>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ kernel/futex.c | 14 +++++++++++---
+ 1 file changed, 11 insertions(+), 3 deletions(-)
+
+--- a/kernel/futex.c
++++ b/kernel/futex.c
+@@ -762,10 +762,18 @@ retry:
+ return -EDEADLK;
+
+ /*
+- * Surprise - we got the lock. Just return to userspace:
++ * Surprise - we got the lock, but we do not trust user space at all.
+ */
+- if (unlikely(!curval))
+- return 1;
++ if (unlikely(!curval)) {
++ /*
++ * We verify whether there is kernel state for this
++ * futex. If not, we can safely assume, that the 0 ->
++ * TID transition is correct. If state exists, we do
++ * not bother to fixup the user space state as it was
++ * corrupted already.
++ */
++ return futex_top_waiter(hb, key) ? -EINVAL : 1;
++ }
+
+ uval = curval;
+