132 lines
4.6 KiB
Diff
132 lines
4.6 KiB
Diff
Return-Path: <tglx@linutronix.de>
|
|
Received: from Galois.linutronix.de (Galois.linutronix.de
|
|
[IPv6:2001:470:1f0b:db:abcd:42:0:1]) by vinyl.outflux.net
|
|
(8.14.4/8.14.4/Debian-4.1ubuntu1) with ESMTP id s53CRBS5010805
|
|
(version=TLSv1/SSLv3 cipher=DHE-RSA-AES128-SHA bits=128 verify=NO) for
|
|
<kees@outflux.net>; Tue, 3 Jun 2014 05:27:17 -0700
|
|
Received: from localhost ([127.0.0.1] helo=[127.0.1.1]) by
|
|
Galois.linutronix.de with esmtp (Exim 4.80) (envelope-from
|
|
<tglx@linutronix.de>) id 1Wrno4-0002Sb-9g; Tue, 03 Jun 2014 14:27:08 +0200
|
|
Message-Id: <20140603121944.949737592@linutronix.de>
|
|
User-Agent: quilt/0.63-1
|
|
Date: Tue, 03 Jun 2014 12:27:07 -0000
|
|
From: Thomas Gleixner <tglx@linutronix.de>
|
|
To: Linus Torvalds <torvalds@linux-foundation.org>
|
|
Cc: Darren Hart <dvhart@linux.intel.com>, Kees Cook <kees@outflux.net>,
|
|
"security@kernel.org" <security@kernel.org>, linux-distros@vs.openwall.org,
|
|
Sebastian Krahmer <krahmer@suse.de>, Ingo Molnar <mingo@kernel.org>, Kees
|
|
Cook <keescook@chromium.org>, Will Drewry <wad@chromium.org>
|
|
Subject: [patch 3/4] futex: Always cleanup owner tid in unlock_pi
|
|
References: <20140603113303.799564413@linutronix.de>
|
|
MIME-Version: 1.0
|
|
Content-Type: text/plain; charset=ISO-8859-15
|
|
Content-Disposition: inline; filename=futex-cleanup-owner-tid-on-unlock.patch
|
|
X-Linutronix-Spam-Score: -1.0
|
|
X-Linutronix-Spam-Level: -
|
|
X-Linutronix-Spam-Status: No , -1.0 points, 5.0 required,
|
|
ALL_TRUSTED=-1,SHORTCIRCUIT=-0.0001
|
|
Received-SPF: none (linutronix.de: No applicable sender policy available)
|
|
receiver=smtp.outflux.net; identity=mailfrom;
|
|
envelope-from="tglx@linutronix.de"; helo=Galois.linutronix.de;
|
|
client-ip="2001:470:1f0b:db:abcd:42:0:1"
|
|
Envelope-To: kees@outflux.net
|
|
X-MIMEDefang-Filter: outflux$Revision: 1.316 $
|
|
X-HELO: Galois.linutronix.de
|
|
X-Spam-Status: No, hits=-0.651 required=5 tests=RP_MATCHES_RCVD
|
|
X-Spam-Checker-Version: SpamAssassin 3.4.0-outflux_revision__1.66__
|
|
X-Scanned-By: MIMEDefang 2.73
|
|
Content-Length: 2854
|
|
Lines: 93
|
|
|
|
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>
|
|
Cc: stable@vger.kernel.org
|
|
---
|
|
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);
|