public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Thomas Gleixner <tglx@linutronix.de>
To: LKML <linux-kernel@vger.kernel.org>
Cc: Dave Jones <davej@redhat.com>,
	Linus Torvalds <torvalds@linux-foundation.org>,
	Peter Zijlstra <peterz@infradead.org>,
	Darren Hart <darren@dvhart.com>,
	Davidlohr Bueso <davidlohr@hp.com>,
	Ingo Molnar <mingo@kernel.org>,
	Steven Rostedt <rostedt@goodmis.org>,
	Clark Williams <williams@redhat.com>,
	Paul McKenney <paulmck@linux.vnet.ibm.com>,
	Lai Jiangshan <laijs@cn.fujitsu.com>,
	Roland McGrath <roland@hack.frob.com>,
	Carlos ODonell <carlos@redhat.com>,
	Jakub Jelinek <jakub@redhat.com>,
	Michael Kerrisk <mtk.manpages@gmail.com>,
	Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Subject: [patch 2/3] futex: Add another early deadlock detection check
Date: Mon, 12 May 2014 20:45:34 -0000	[thread overview]
Message-ID: <20140512201701.097349971@linutronix.de> (raw)
In-Reply-To: 20140512190438.314125476@linutronix.de

[-- Attachment #1: futex-add-early-deadlock-detection.patch --]
[-- Type: text/plain, Size: 4619 bytes --]

Dave Jones trinity syscall fuzzer exposed an issue in the deadlock
detection code of rtmutex:
  http://lkml.kernel.org/r/20140429151655.GA14277@redhat.com

That underlying issue has been fixed with a patch to the rtmutex code,
but the futex code must not call into rtmutex in that case because
    - it can detect that issue early
    - it avoids a different and more complex fixup for backing out

If the user space variable got manipulated to 0x80000000 which means
no lock holder, but the waiters bit set and an active pi_state in the
kernel is found we can figure out the recursive locking issue by
looking at the pi_state owner. If that is the current task, then we
can safely return -EDEADLK.

The check should have been added in commit 59fa62451 (futex: Handle
futex_pi OWNER_DIED take over correctly) already, but I did not see
the above issue caused by user space manipulation back then.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: stable@vger.kernel.org
---
 kernel/futex.c |   47 ++++++++++++++++++++++++++++++++++-------------
 1 file changed, 34 insertions(+), 13 deletions(-)

Index: linux-2.6/kernel/futex.c
===================================================================
--- linux-2.6.orig/kernel/futex.c
+++ linux-2.6/kernel/futex.c
@@ -745,7 +745,8 @@ void exit_pi_state_list(struct task_stru
 
 static int
 lookup_pi_state(u32 uval, struct futex_hash_bucket *hb,
-		union futex_key *key, struct futex_pi_state **ps)
+		union futex_key *key, struct futex_pi_state **ps,
+		struct task_struct *task)
 {
 	struct futex_pi_state *pi_state = NULL;
 	struct futex_q *this, *next;
@@ -786,6 +787,16 @@ lookup_pi_state(u32 uval, struct futex_h
 					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.
+			 */
+			if (task && pi_state->owner == task)
+				return -EDEADLK;
+
 			atomic_inc(&pi_state->refcount);
 			*ps = pi_state;
 
@@ -935,7 +946,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);
+	ret = lookup_pi_state(uval, hb, key, ps, task);
 
 	if (unlikely(ret)) {
 		switch (ret) {
@@ -1347,7 +1358,7 @@ void requeue_pi_wake_futex(struct futex_
  *
  * Return:
  *  0 - failed to acquire the lock atomically;
- *  1 - acquired the lock;
+ * >0 - acquired the lock, return value is vpid of the top_waiter
  * <0 - error
  */
 static int futex_proxy_trylock_atomic(u32 __user *pifutex,
@@ -1358,7 +1369,7 @@ static int futex_proxy_trylock_atomic(u3
 {
 	struct futex_q *top_waiter = NULL;
 	u32 curval;
-	int ret;
+	int ret, vpid;
 
 	if (get_futex_value_locked(&curval, pifutex))
 		return -EFAULT;
@@ -1386,11 +1397,13 @@ static int futex_proxy_trylock_atomic(u3
 	 * the contended case or if set_waiters is 1.  The pi_state is returned
 	 * in ps in contended cases.
 	 */
+	vpid = task_pid_vnr(top_waiter->task);
 	ret = futex_lock_pi_atomic(pifutex, hb2, key2, ps, top_waiter->task,
 				   set_waiters);
-	if (ret == 1)
+	if (ret == 1) {
 		requeue_pi_wake_futex(top_waiter, key2, hb2);
-
+		return vpid;
+	}
 	return ret;
 }
 
@@ -1421,7 +1434,6 @@ static int futex_requeue(u32 __user *uad
 	struct futex_pi_state *pi_state = NULL;
 	struct futex_hash_bucket *hb1, *hb2;
 	struct futex_q *this, *next;
-	u32 curval2;
 
 	if (requeue_pi) {
 		/*
@@ -1509,16 +1521,25 @@ retry_private:
 		 * At this point the top_waiter has either taken uaddr2 or is
 		 * waiting on it.  If the former, then the pi_state will not
 		 * exist yet, look it up one more time to ensure we have a
-		 * reference to it.
+		 * reference to it. If the lock was taken, ret contains the
+		 * vpid of the top waiter task.
 		 */
-		if (ret == 1) {
+		if (ret > 0) {
 			WARN_ON(pi_state);
 			drop_count++;
 			task_count++;
-			ret = get_futex_value_locked(&curval2, uaddr2);
-			if (!ret)
-				ret = lookup_pi_state(curval2, hb2, &key2,
-						      &pi_state);
+			/*
+			 * If we acquired the lock, then the user
+			 * space value of uaddr2 should be vpid. It
+			 * cannot be changed by the top waiter as it
+			 * is blocked on hb2 lock if it tries to do
+			 * so. If something fiddled with it behind our
+			 * back the pi state lookup might unearth
+			 * it. So we rather use the known value than
+			 * rereading and handing potential crap to
+			 * lookup_pi_state.
+			 */
+			ret = lookup_pi_state(ret, hb2, &key2, &pi_state, NULL);
 		}
 
 		switch (ret) {



  parent reply	other threads:[~2014-05-12 20:45 UTC|newest]

Thread overview: 53+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-05-12 20:45 [patch 0/3] futex/rtmutex: Fix issues exposed by trinity Thomas Gleixner
2014-05-12 20:45 ` [patch 1/3] rtmutex: Add missing deadlock check Thomas Gleixner
2014-05-13  5:51   ` Lai Jiangshan
2014-05-13  8:45     ` Thomas Gleixner
2014-05-13  8:48     ` Peter Zijlstra
2014-05-13 16:12       ` Paul E. McKenney
2014-05-13 19:42       ` Thomas Gleixner
2014-05-13 20:20         ` Steven Rostedt
2014-05-13 20:36           ` Paul E. McKenney
2014-05-13 21:27             ` Thomas Gleixner
2014-05-13 22:00               ` Paul E. McKenney
2014-05-13 22:44                 ` Steven Rostedt
2014-05-13 23:27                   ` Paul E. McKenney
2014-05-13 23:53                     ` Steven Rostedt
2014-05-14  0:12                       ` Paul E. McKenney
2014-05-14  6:54                       ` Thomas Gleixner
     [not found]                         ` <CAGChsmO9GO1Z2VBbw7uLtTXpYowdoUQbK8C3=Dt2jtGAnc6D2A@mail.gmail.com>
2014-05-14 13:33                           ` Thomas Gleixner
2014-05-14  6:42                   ` Thomas Gleixner
2014-05-14 12:59     ` Thomas Gleixner
2014-05-12 20:45 ` Thomas Gleixner [this message]
2014-05-19 12:22   ` [tip:core/urgent] futex: Add another early deadlock detection check tip-bot for Thomas Gleixner
2014-05-12 20:45 ` [patch 3/3] futex: Prevent attaching to kernel threads Thomas Gleixner
2014-05-12 20:54   ` Peter Zijlstra
2014-05-12 21:16     ` Thomas Gleixner
2014-05-12 21:59   ` Davidlohr Bueso
2014-05-12 22:18     ` Thomas Gleixner
2014-05-19 12:22   ` [tip:core/urgent] " tip-bot for Thomas Gleixner
2014-05-12 21:37 ` [patch 0/3] futex/rtmutex: Fix issues exposed by trinity Steven Rostedt
2014-05-12 21:52   ` Thomas Gleixner
2014-05-12 22:08     ` Steven Rostedt
2014-05-12 22:37       ` Thomas Gleixner
2014-05-12 23:18         ` Steven Rostedt
2014-05-13  6:37   ` Ingo Molnar
2014-05-13  3:54 ` Darren Hart
2014-05-13  9:08   ` Thomas Gleixner
2014-05-14  7:06     ` Carlos O'Donell
2014-05-14 10:26       ` Thomas Gleixner
2014-05-14 20:59         ` Carlos O'Donell
2014-05-14 22:54           ` Thomas Gleixner
2014-05-15  7:37           ` Peter Zijlstra
2014-05-15  8:25           ` Peter Zijlstra
2014-05-16 18:21             ` Carlos O'Donell
2014-05-14  6:58   ` Carlos O'Donell
2014-05-14  9:22     ` Peter Zijlstra
2014-05-14 21:17       ` Carlos O'Donell
2014-05-14 23:11         ` Thomas Gleixner
2014-05-16 17:54           ` Carlos O'Donell
2014-05-15  8:07         ` Peter Zijlstra
2014-05-16 18:14           ` Carlos O'Donell
2014-05-14  9:53     ` Thomas Gleixner
2014-05-14 10:07       ` Peter Zijlstra
2014-05-14 10:28         ` Thomas Gleixner
2014-05-16 17:55           ` Carlos O'Donell

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=20140512201701.097349971@linutronix.de \
    --to=tglx@linutronix.de \
    --cc=bigeasy@linutronix.de \
    --cc=carlos@redhat.com \
    --cc=darren@dvhart.com \
    --cc=davej@redhat.com \
    --cc=davidlohr@hp.com \
    --cc=jakub@redhat.com \
    --cc=laijs@cn.fujitsu.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mingo@kernel.org \
    --cc=mtk.manpages@gmail.com \
    --cc=paulmck@linux.vnet.ibm.com \
    --cc=peterz@infradead.org \
    --cc=roland@hack.frob.com \
    --cc=rostedt@goodmis.org \
    --cc=torvalds@linux-foundation.org \
    --cc=williams@redhat.com \
    /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