diff --git a/futex-always-cleanup-owner-tid-in-unlock_pi.patch b/futex-always-cleanup-owner-tid-in-unlock_pi.patch deleted file mode 100644 index 64d765d..0000000 --- a/futex-always-cleanup-owner-tid-in-unlock_pi.patch +++ /dev/null @@ -1,105 +0,0 @@ -Bugzilla: 1105609 -Upstream-status: 3.15 and queued for 3.14.6 - -From 13fbca4c6ecd96ec1a1cfa2e4f2ce191fe928a5e Mon Sep 17 00:00:00 2001 -From: Thomas Gleixner -Date: Tue, 3 Jun 2014 12:27:07 +0000 -Subject: futex: Always cleanup owner tid in unlock_pi - -From: Thomas Gleixner - -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 -Cc: Kees Cook -Cc: Will Drewry -Cc: Darren Hart -Signed-off-by: Linus Torvalds -Signed-off-by: Greg Kroah-Hartman - ---- - kernel/futex.c | 44 ++++++++++++++++++++------------------------ - 1 file changed, 20 insertions(+), 24 deletions(-) - ---- a/kernel/futex.c -+++ b/kernel/futex.c -@@ -1038,6 +1038,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; -@@ -1061,23 +1062,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); -@@ -2337,9 +2334,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; - /* -@@ -2369,11 +2367,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); diff --git a/futex-make-lookup_pi_state-more-robust.patch b/futex-make-lookup_pi_state-more-robust.patch deleted file mode 100644 index 2e7c508..0000000 --- a/futex-make-lookup_pi_state-more-robust.patch +++ /dev/null @@ -1,282 +0,0 @@ -Bugzilla: 1105609 -Upstream-status: 3.15 and queued for 3.14.6 - -From 54a217887a7b658e2650c3feff22756ab80c7339 Mon Sep 17 00:00:00 2001 -From: Thomas Gleixner -Date: Tue, 3 Jun 2014 12:27:08 +0000 -Subject: futex: Make lookup_pi_state more robust - -From: Thomas Gleixner - -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 -Cc: Kees Cook -Cc: Will Drewry -Cc: Darren Hart -Signed-off-by: Linus Torvalds -Signed-off-by: Greg Kroah-Hartman - ---- - kernel/futex.c | 134 +++++++++++++++++++++++++++++++++++++++++++++------------ - 1 file changed, 106 insertions(+), 28 deletions(-) - ---- a/kernel/futex.c -+++ b/kernel/futex.c -@@ -729,10 +729,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; -@@ -742,12 +790,13 @@ lookup_pi_state(u32 uval, struct futex_h - plist_for_each_entry_safe(this, next, &hb->chain, 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; -@@ -755,44 +804,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; -@@ -825,6 +900,9 @@ lookup_pi_state(u32 uval, struct futex_h - return ret; - } - -+ /* -+ * No existing pi state. First waiter. [2] -+ */ - pi_state = alloc_pi_state(); - - /* -@@ -945,7 +1023,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) { -@@ -1551,7 +1629,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) { diff --git a/futex-prevent-attaching-to-kernel-threads.patch b/futex-prevent-attaching-to-kernel-threads.patch deleted file mode 100644 index df38b04..0000000 --- a/futex-prevent-attaching-to-kernel-threads.patch +++ /dev/null @@ -1,58 +0,0 @@ -Bugzilla: 1105609 -Upstream-status: 3.15 and queued for 3.14.6 - -From f0d71b3dcb8332f7971b5f2363632573e6d9486a Mon Sep 17 00:00:00 2001 -From: Thomas Gleixner -Date: Mon, 12 May 2014 20:45:35 +0000 -Subject: futex: Prevent attaching to kernel threads - -From: Thomas Gleixner - -commit f0d71b3dcb8332f7971b5f2363632573e6d9486a upstream. - -We happily allow userspace to declare a random kernel thread to be the -owner of a user space PI futex. - -Found while analysing the fallout of Dave Jones syscall fuzzer. - -We also should validate the thread group for private futexes and find -some fast way to validate whether the "alleged" owner has RW access on -the file which backs the SHM, but that's a separate issue. - -Signed-off-by: Thomas Gleixner -Cc: Dave Jones -Cc: Linus Torvalds -Cc: Peter Zijlstra -Cc: Darren Hart -Cc: Davidlohr Bueso -Cc: Steven Rostedt -Cc: Clark Williams -Cc: Paul McKenney -Cc: Lai Jiangshan -Cc: Roland McGrath -Cc: Carlos ODonell -Cc: Jakub Jelinek -Cc: Michael Kerrisk -Cc: Sebastian Andrzej Siewior -Link: http://lkml.kernel.org/r/20140512201701.194824402@linutronix.de -Signed-off-by: Thomas Gleixner -Signed-off-by: Greg Kroah-Hartman - ---- - kernel/futex.c | 5 +++++ - 1 file changed, 5 insertions(+) - ---- a/kernel/futex.c -+++ b/kernel/futex.c -@@ -800,6 +800,11 @@ lookup_pi_state(u32 uval, struct futex_h - if (!p) - return -ESRCH; - -+ if (!p->mm) { -+ put_task_struct(p); -+ return -EPERM; -+ } -+ - /* - * We need to look at the task state flags to figure out, - * whether the task is exiting. To protect against the do_exit diff --git a/futex-prevent-requeue-pi-on-same-futex.patch-futex-forbid-uaddr-uaddr2-in-futex_requeue-...-requeue_pi-1.patch b/futex-prevent-requeue-pi-on-same-futex.patch-futex-forbid-uaddr-uaddr2-in-futex_requeue-...-requeue_pi-1.patch deleted file mode 100644 index 8f29ef5..0000000 --- a/futex-prevent-requeue-pi-on-same-futex.patch-futex-forbid-uaddr-uaddr2-in-futex_requeue-...-requeue_pi-1.patch +++ /dev/null @@ -1,86 +0,0 @@ -Bugzilla: 1105609 -Upstream-status: 3.15 and queued for 3.14.6 - -From e9c243a5a6de0be8e584c604d353412584b592f8 Mon Sep 17 00:00:00 2001 -From: Thomas Gleixner -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 - -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 -Signed-off-by: Kees Cook -Signed-off-by: Thomas Gleixner -Reviewed-by: Darren Hart -Signed-off-by: Linus Torvalds -Signed-off-by: Greg Kroah-Hartman - ---- - kernel/futex.c | 25 +++++++++++++++++++++++++ - 1 file changed, 25 insertions(+) - ---- a/kernel/futex.c -+++ b/kernel/futex.c -@@ -1428,6 +1428,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. - */ -@@ -1465,6 +1472,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); - -@@ -2511,6 +2527,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); - diff --git a/futex-validate-atomic-acquisition-in-futex_lock_pi_atomic.patch b/futex-validate-atomic-acquisition-in-futex_lock_pi_atomic.patch deleted file mode 100644 index afd0e3c..0000000 --- a/futex-validate-atomic-acquisition-in-futex_lock_pi_atomic.patch +++ /dev/null @@ -1,59 +0,0 @@ -Bugzilla: 1105609 -Upstream-status: 3.15 and queued for 3.14.6 - -From b3eaa9fc5cd0a4d74b18f6b8dc617aeaf1873270 Mon Sep 17 00:00:00 2001 -From: Thomas Gleixner -Date: Tue, 3 Jun 2014 12:27:06 +0000 -Subject: futex: Validate atomic acquisition in futex_lock_pi_atomic() - -From: Thomas Gleixner - -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 -Cc: Kees Cook -Cc: Will Drewry -Signed-off-by: Thomas Gleixner -Signed-off-by: Linus Torvalds -Signed-off-by: Greg Kroah-Hartman - ---- - kernel/futex.c | 14 +++++++++++--- - 1 file changed, 11 insertions(+), 3 deletions(-) - ---- a/kernel/futex.c -+++ b/kernel/futex.c -@@ -896,10 +896,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; -