From: Steven Rostedt <rostedt@goodmis.org>
To: linux-kernel@vger.kernel.org,
linux-rt-users <linux-rt-users@vger.kernel.org>
Cc: Thomas Gleixner <tglx@linutronix.de>,
Carsten Emde <C.Emde@osadl.org>,
Sebastian Andrzej Siewior <bigeasy@linutronix.de>,
John Kacur <jkacur@redhat.com>,
Paul Gortmaker <paul.gortmaker@windriver.com>,
Peter Zijlstra <peterz@infradead.org>,
Darren Hart <darren@dvhart.com>,
Davidlohr Bueso <davidlohr@hp.com>, Kees Cook <kees@outflux.net>,
<wad@chromium.org>
Subject: [PATCH RT 12/36] futex: Make unlock_pi more robust
Date: Thu, 12 Mar 2015 15:21:51 -0400 [thread overview]
Message-ID: <20150312192156.401155402@goodmis.org> (raw)
In-Reply-To: 20150312192139.799127123@goodmis.org
[-- Attachment #1: 0012-futex-Make-unlock_pi-more-robust.patch --]
[-- Type: text/plain, Size: 4934 bytes --]
3.12.38-rt53-rc1 stable review patch.
If anyone has any objections, please let me know.
------------------
From: Thomas Gleixner <tglx@linutronix.de>
upstream commit: ccf9e6a80d9e1b9df69c98e6b9745cf49869ee15
The kernel tries to atomically unlock the futex without checking
whether there is kernel state associated to the futex.
So if user space manipulated the user space value, this will leave
kernel internal state around associated to the owner task.
For robustness sake, lookup first whether there are waiters on the
futex. If there are waiters, wake the top priority waiter with all the
proper sanity checks applied.
If there are no waiters, do the atomic release. We do not have to
preserve the waiters bit in this case, because a potentially incoming
waiter is blocked on the hb->lock and will acquire the futex
atomically. We neither have to preserve the owner died bit. The caller
is the owner and it was supposed to cleanup the mess.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Darren Hart <darren@dvhart.com>
Cc: Davidlohr Bueso <davidlohr@hp.com>
Cc: Kees Cook <kees@outflux.net>
Cc: wad@chromium.org
Link: http://lkml.kernel.org/r/20140611204237.016987332@linutronix.de
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
---
kernel/futex.c | 80 +++++++++++++++++++---------------------------------------
1 file changed, 26 insertions(+), 54 deletions(-)
diff --git a/kernel/futex.c b/kernel/futex.c
index 1170418e4dd6..4dfbd5d57c5c 100644
--- a/kernel/futex.c
+++ b/kernel/futex.c
@@ -1041,22 +1041,6 @@ static int wake_futex_pi(u32 __user *uaddr, u32 uval, struct futex_q *this)
return 0;
}
-static int unlock_futex_pi(u32 __user *uaddr, u32 uval)
-{
- u32 uninitialized_var(oldval);
-
- /*
- * There is no waiter, so we unlock the futex. The owner died
- * bit has not to be preserved here. We are the owner:
- */
- if (cmpxchg_futex_value_locked(&oldval, uaddr, uval, 0))
- return -EFAULT;
- if (oldval != uval)
- return -EAGAIN;
-
- return 0;
-}
-
/*
* Express the locking dependencies for lockdep:
*/
@@ -2250,11 +2234,10 @@ uaddr_faulted:
*/
static int futex_unlock_pi(u32 __user *uaddr, unsigned int flags)
{
- struct futex_hash_bucket *hb;
- struct futex_q *this, *next;
- struct plist_head *head;
+ u32 uninitialized_var(curval), uval, vpid = task_pid_vnr(current);
union futex_key key = FUTEX_KEY_INIT;
- u32 uval, vpid = task_pid_vnr(current);
+ struct futex_hash_bucket *hb;
+ struct futex_q *match;
int ret;
retry:
@@ -2267,61 +2250,50 @@ retry:
return -EPERM;
ret = get_futex_key(uaddr, flags & FLAGS_SHARED, &key, VERIFY_WRITE);
- if (unlikely(ret != 0))
- goto out;
+ if (ret)
+ return ret;
hb = hash_futex(&key);
spin_lock(&hb->lock);
/*
- * To avoid races, try to do the TID -> 0 atomic transition
- * again. If it succeeds then we can return without waking
- * anyone else up. We only try this if neither the waiters nor
- * the owner died bit are set.
+ * Check waiters first. We do not trust user space values at
+ * all and we at least want to know if user space fiddled
+ * with the futex value instead of blindly unlocking.
*/
- if (!(uval & ~FUTEX_TID_MASK) &&
- cmpxchg_futex_value_locked(&uval, uaddr, vpid, 0))
- goto pi_faulted;
- /*
- * Rare case: we managed to release the lock atomically,
- * no need to wake anyone else up:
- */
- if (unlikely(uval == vpid))
- goto out_unlock;
-
- /*
- * Ok, other tasks may need to be woken up - check waiters
- * and do the wakeup if necessary:
- */
- head = &hb->chain;
-
- plist_for_each_entry_safe(this, next, head, list) {
- if (!match_futex (&this->key, &key))
- continue;
- ret = wake_futex_pi(uaddr, uval, this);
+ match = futex_top_waiter(hb, &key);
+ if (match) {
+ ret = wake_futex_pi(uaddr, uval, match);
/*
- * The atomic access to the futex value
- * generated a pagefault, so retry the
- * user-access and the wakeup:
+ * The atomic access to the futex value generated a
+ * pagefault, so retry the user-access and the wakeup:
*/
if (ret == -EFAULT)
goto pi_faulted;
goto out_unlock;
}
+
/*
- * No waiters - kernel unlocks the futex:
+ * We have no kernel internal state, i.e. no waiters in the
+ * kernel. Waiters which are about to queue themselves are stuck
+ * on hb->lock. So we can safely ignore them. We do neither
+ * preserve the WAITERS bit not the OWNER_DIED one. We are the
+ * owner.
*/
- ret = unlock_futex_pi(uaddr, uval);
- if (ret == -EFAULT)
+ if (cmpxchg_futex_value_locked(&curval, uaddr, uval, 0))
goto pi_faulted;
+ /*
+ * If uval has changed, let user space handle it.
+ */
+ ret = (curval == uval) ? 0 : -EAGAIN;
+
out_unlock:
spin_unlock(&hb->lock);
put_futex_key(&key);
-
-out:
return ret;
+
pi_faulted:
spin_unlock(&hb->lock);
put_futex_key(&key);
--
2.1.4
next prev parent reply other threads:[~2015-03-12 19:30 UTC|newest]
Thread overview: 37+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-03-12 19:21 [PATCH RT 00/36] Linux 3.12.38-rt53-rc1 Steven Rostedt
2015-03-12 19:21 ` [PATCH RT 01/36] gpio: omap: use raw locks for locking Steven Rostedt
2015-03-12 19:21 ` [PATCH RT 02/36] create-rt-enqueue Steven Rostedt
2015-03-12 19:21 ` [PATCH RT 03/36] rtmutex: Simplify rtmutex_slowtrylock() Steven Rostedt
2015-03-12 19:21 ` [PATCH RT 04/36] rtmutex: Simplify and document try_to_take_rtmutex() Steven Rostedt
2015-03-12 19:21 ` [PATCH RT 05/36] rtmutex: No need to keep task ref for lock owner check Steven Rostedt
2015-03-12 19:21 ` [PATCH RT 06/36] rtmutex: Clarify the boost/deboost part Steven Rostedt
2015-03-12 19:21 ` [PATCH RT 07/36] rtmutex: Document pi chain walk Steven Rostedt
2015-03-12 19:21 ` [PATCH RT 08/36] rtmutex: Simplify remove_waiter() Steven Rostedt
2015-03-12 19:21 ` [PATCH RT 09/36] rtmutex: Confine deadlock logic to futex Steven Rostedt
2015-03-12 19:21 ` [PATCH RT 10/36] rtmutex: Cleanup deadlock detector debug logic Steven Rostedt
2015-03-12 19:21 ` [PATCH RT 11/36] rtmutex: Avoid pointless requeueing in the deadlock detection chain walk Steven Rostedt
2015-03-12 19:21 ` Steven Rostedt [this message]
2015-03-12 19:21 ` [PATCH RT 13/36] futex: Use futex_top_waiter() in lookup_pi_state() Steven Rostedt
2015-03-12 19:21 ` [PATCH RT 14/36] futex: Split out the waiter check from lookup_pi_state() Steven Rostedt
2015-03-12 19:21 ` [PATCH RT 15/36] futex: Split out the first waiter attachment " Steven Rostedt
2015-03-12 19:21 ` [PATCH RT 16/36] futex: Simplify futex_lock_pi_atomic() and make it more robust Steven Rostedt
2015-03-12 19:21 ` [PATCH RT 17/36] rt-mutex: avoid a NULL pointer dereference on deadlock Steven Rostedt
2015-03-12 19:21 ` [PATCH RT 18/36] rt: fix __ww_mutex_lock_interruptible() lockdep annotation Steven Rostedt
2015-03-12 19:21 ` [PATCH RT 19/36] rtmutex: enable deadlock detection in ww_mutex_lock functions Steven Rostedt
2015-03-12 19:21 ` [PATCH RT 20/36] x86: UV: raw_spinlock conversion Steven Rostedt
2015-03-13 15:13 ` [PATCH RT 21/36] ARM: enable irq in translation/section permission fault handlers Steven Rostedt
2015-03-12 19:22 ` [PATCH RT 22/36] arm/futex: disable preemption during futex_atomic_cmpxchg_inatomic() Steven Rostedt
2015-03-12 19:22 ` [PATCH RT 23/36] ARM: cmpxchg: define __HAVE_ARCH_CMPXCHG for armv6 and later Steven Rostedt
2015-03-12 19:22 ` [PATCH RT 24/36] sas-ata/isci: dontt disable interrupts in qc_issue handler Steven Rostedt
2015-03-12 19:22 ` [PATCH RT 25/36] scheduling while atomic in cgroup code Steven Rostedt
2015-03-12 19:22 ` [PATCH RT 26/36] work-simple: Simple work queue implemenation Steven Rostedt
2015-03-12 19:22 ` [PATCH RT 27/36] sunrpc: make svc_xprt_do_enqueue() use get_cpu_light() Steven Rostedt
2015-03-12 19:22 ` [PATCH RT 28/36] locking: ww_mutex: fix ww_mutex vs self-deadlock Steven Rostedt
2015-03-12 19:22 ` [PATCH RT 29/36] thermal: Defer thermal wakups to threads Steven Rostedt
2015-03-12 19:22 ` [PATCH RT 30/36] lockdep: selftest: fix warnings due to missing PREEMPT_RT conditionals Steven Rostedt
2015-03-12 19:22 ` [PATCH RT 31/36] fs/aio: simple simple work Steven Rostedt
2015-03-12 19:22 ` [PATCH RT 32/36] timers: Track total number of timers in list Steven Rostedt
2015-03-12 19:22 ` [PATCH RT 33/36] timers: Reduce __run_timers() latency for empty list Steven Rostedt
2015-03-12 19:22 ` [PATCH RT 34/36] timers: Reduce future __run_timers() latency for newly emptied list Steven Rostedt
2015-03-12 19:22 ` [PATCH RT 35/36] timers: Reduce future __run_timers() latency for first add to empty list Steven Rostedt
2015-03-12 19:22 ` [PATCH RT 36/36] Linux 3.12.38-rt53-rc1 Steven Rostedt
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20150312192156.401155402@goodmis.org \
--to=rostedt@goodmis.org \
--cc=C.Emde@osadl.org \
--cc=bigeasy@linutronix.de \
--cc=darren@dvhart.com \
--cc=davidlohr@hp.com \
--cc=jkacur@redhat.com \
--cc=kees@outflux.net \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-rt-users@vger.kernel.org \
--cc=paul.gortmaker@windriver.com \
--cc=peterz@infradead.org \
--cc=tglx@linutronix.de \
--cc=wad@chromium.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox