source:
trunk/server/common/patches/cve-2014-3153-3.patch
@
2583
Last change on this file since 2583 was 2557, checked in by achernya, 10 years ago | |
---|---|
File size: 3.2 KB |
-
kernel/futex.c
From 9ad5dabd87e8dd5506529e12e4e8c7b25fb88d7a Mon Sep 17 00:00:00 2001 From: Thomas Gleixner <tglx@linutronix.de> Date: Tue, 3 Jun 2014 12:27:07 +0000 Subject: [PATCH 3/4] futex: Always cleanup owner tid in unlock_pi 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 | 40 ++++++++++++++++++---------------------- 1 file changed, 18 insertions(+), 22 deletions(-) diff --git a/kernel/futex.c b/kernel/futex.c index 8c1e6d0..9720c42 100644
a b static int wake_futex_pi(u32 __user *uaddr, u32 uval, struct futex_q *this) 903 903 struct task_struct *new_owner; 904 904 struct futex_pi_state *pi_state = this->pi_state; 905 905 u32 uninitialized_var(curval), newval; 906 int ret = 0; 906 907 907 908 if (!pi_state) 908 909 return -EINVAL; … … static int wake_futex_pi(u32 __user *uaddr, u32 uval, struct futex_q *this) 926 927 new_owner = this->task; 927 928 928 929 /* 929 * We pass it to the next owner. (The WAITERS bit is always930 * kept enabled while there is PI state around. We must also931 * preserve the owner died bit.)930 * We pass it to the next owner. The WAITERS bit is always 931 * kept enabled while there is PI state around. We cleanup the 932 * owner died bit, because we are the owner. 932 933 */ 933 if (!(uval & FUTEX_OWNER_DIED)) { 934 int ret = 0; 935 936 newval = FUTEX_WAITERS | task_pid_vnr(new_owner); 934 newval = FUTEX_WAITERS | task_pid_vnr(new_owner); 937 935 938 if (cmpxchg_futex_value_locked(&curval, uaddr, uval, newval)) 939 ret = -EFAULT; 940 else if (curval != uval) 941 ret = -EINVAL; 942 if (ret) { 943 raw_spin_unlock(&pi_state->pi_mutex.wait_lock); 944 return ret; 945 } 936 if (cmpxchg_futex_value_locked(&curval, uaddr, uval, newval)) 937 ret = -EFAULT; 938 else if (curval != uval) 939 ret = -EINVAL; 940 if (ret) { 941 raw_spin_unlock(&pi_state->pi_mutex.wait_lock); 942 return ret; 946 943 } 947 944 948 945 raw_spin_lock_irq(&pi_state->owner->pi_lock); … … retry: 2187 2184 /* 2188 2185 * To avoid races, try to do the TID -> 0 atomic transition 2189 2186 * again. If it succeeds then we can return without waking 2190 * anyone else up: 2187 * anyone else up. We only try this if neither the waiters nor 2188 * the owner died bit are set. 2191 2189 */ 2192 if (!(uval & FUTEX_OWNER_DIED) &&2190 if (!(uval & ~FUTEX_TID_MASK) && 2193 2191 cmpxchg_futex_value_locked(&uval, uaddr, vpid, 0)) 2194 2192 goto pi_faulted; 2195 2193 /* … … retry: 2221 2219 /* 2222 2220 * No waiters - kernel unlocks the futex: 2223 2221 */ 2224 if (!(uval & FUTEX_OWNER_DIED)) { 2225 ret = unlock_futex_pi(uaddr, uval); 2226 if (ret == -EFAULT) 2227 goto pi_faulted; 2228 } 2222 ret = unlock_futex_pi(uaddr, uval); 2223 if (ret == -EFAULT) 2224 goto pi_faulted; 2229 2225 2230 2226 out_unlock: 2231 2227 spin_unlock(&hb->lock);
Note: See TracBrowser
for help on using the repository browser.