aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2014-05-12 16:45:34 -0400
committerThomas Gleixner <tglx@linutronix.de>2014-05-19 08:18:49 -0400
commit866293ee54227584ffcb4a42f69c1f365974ba7f (patch)
tree5ecf5d09dc2348c583790d4d1cc308aaca4870be
parentd6d211db37e75de2ddc3a4f979038c40df7cc79c (diff)
futex: Add another early deadlock detection check
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: Dave Jones <davej@redhat.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Darren Hart <darren@dvhart.com> Cc: Davidlohr Bueso <davidlohr@hp.com> Cc: Steven Rostedt <rostedt@goodmis.org> Cc: Clark Williams <williams@redhat.com> Cc: Paul McKenney <paulmck@linux.vnet.ibm.com> Cc: Lai Jiangshan <laijs@cn.fujitsu.com> Cc: Roland McGrath <roland@hack.frob.com> Cc: Carlos ODonell <carlos@redhat.com> Cc: Jakub Jelinek <jakub@redhat.com> Cc: Michael Kerrisk <mtk.manpages@gmail.com> Cc: Sebastian Andrzej Siewior <bigeasy@linutronix.de> Link: http://lkml.kernel.org/r/20140512201701.097349971@linutronix.de Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Cc: stable@vger.kernel.org
-rw-r--r--kernel/futex.c47
1 files changed, 34 insertions, 13 deletions
diff --git a/kernel/futex.c b/kernel/futex.c
index 5f589279e462..7c68225e3967 100644
--- a/kernel/futex.c
+++ b/kernel/futex.c
@@ -745,7 +745,8 @@ void exit_pi_state_list(struct task_struct *curr)
745 745
746static int 746static int
747lookup_pi_state(u32 uval, struct futex_hash_bucket *hb, 747lookup_pi_state(u32 uval, struct futex_hash_bucket *hb,
748 union futex_key *key, struct futex_pi_state **ps) 748 union futex_key *key, struct futex_pi_state **ps,
749 struct task_struct *task)
749{ 750{
750 struct futex_pi_state *pi_state = NULL; 751 struct futex_pi_state *pi_state = NULL;
751 struct futex_q *this, *next; 752 struct futex_q *this, *next;
@@ -786,6 +787,16 @@ lookup_pi_state(u32 uval, struct futex_hash_bucket *hb,
786 return -EINVAL; 787 return -EINVAL;
787 } 788 }
788 789
790 /*
791 * Protect against a corrupted uval. If uval
792 * is 0x80000000 then pid is 0 and the waiter
793 * bit is set. So the deadlock check in the
794 * calling code has failed and we did not fall
795 * into the check above due to !pid.
796 */
797 if (task && pi_state->owner == task)
798 return -EDEADLK;
799
789 atomic_inc(&pi_state->refcount); 800 atomic_inc(&pi_state->refcount);
790 *ps = pi_state; 801 *ps = pi_state;
791 802
@@ -935,7 +946,7 @@ retry:
935 * We dont have the lock. Look up the PI state (or create it if 946 * We dont have the lock. Look up the PI state (or create it if
936 * we are the first waiter): 947 * we are the first waiter):
937 */ 948 */
938 ret = lookup_pi_state(uval, hb, key, ps); 949 ret = lookup_pi_state(uval, hb, key, ps, task);
939 950
940 if (unlikely(ret)) { 951 if (unlikely(ret)) {
941 switch (ret) { 952 switch (ret) {
@@ -1347,7 +1358,7 @@ void requeue_pi_wake_futex(struct futex_q *q, union futex_key *key,
1347 * 1358 *
1348 * Return: 1359 * Return:
1349 * 0 - failed to acquire the lock atomically; 1360 * 0 - failed to acquire the lock atomically;
1350 * 1 - acquired the lock; 1361 * >0 - acquired the lock, return value is vpid of the top_waiter
1351 * <0 - error 1362 * <0 - error
1352 */ 1363 */
1353static int futex_proxy_trylock_atomic(u32 __user *pifutex, 1364static int futex_proxy_trylock_atomic(u32 __user *pifutex,
@@ -1358,7 +1369,7 @@ static int futex_proxy_trylock_atomic(u32 __user *pifutex,
1358{ 1369{
1359 struct futex_q *top_waiter = NULL; 1370 struct futex_q *top_waiter = NULL;
1360 u32 curval; 1371 u32 curval;
1361 int ret; 1372 int ret, vpid;
1362 1373
1363 if (get_futex_value_locked(&curval, pifutex)) 1374 if (get_futex_value_locked(&curval, pifutex))
1364 return -EFAULT; 1375 return -EFAULT;
@@ -1386,11 +1397,13 @@ static int futex_proxy_trylock_atomic(u32 __user *pifutex,
1386 * the contended case or if set_waiters is 1. The pi_state is returned 1397 * the contended case or if set_waiters is 1. The pi_state is returned
1387 * in ps in contended cases. 1398 * in ps in contended cases.
1388 */ 1399 */
1400 vpid = task_pid_vnr(top_waiter->task);
1389 ret = futex_lock_pi_atomic(pifutex, hb2, key2, ps, top_waiter->task, 1401 ret = futex_lock_pi_atomic(pifutex, hb2, key2, ps, top_waiter->task,
1390 set_waiters); 1402 set_waiters);
1391 if (ret == 1) 1403 if (ret == 1) {
1392 requeue_pi_wake_futex(top_waiter, key2, hb2); 1404 requeue_pi_wake_futex(top_waiter, key2, hb2);
1393 1405 return vpid;
1406 }
1394 return ret; 1407 return ret;
1395} 1408}
1396 1409
@@ -1421,7 +1434,6 @@ static int futex_requeue(u32 __user *uaddr1, unsigned int flags,
1421 struct futex_pi_state *pi_state = NULL; 1434 struct futex_pi_state *pi_state = NULL;
1422 struct futex_hash_bucket *hb1, *hb2; 1435 struct futex_hash_bucket *hb1, *hb2;
1423 struct futex_q *this, *next; 1436 struct futex_q *this, *next;
1424 u32 curval2;
1425 1437
1426 if (requeue_pi) { 1438 if (requeue_pi) {
1427 /* 1439 /*
@@ -1509,16 +1521,25 @@ retry_private:
1509 * At this point the top_waiter has either taken uaddr2 or is 1521 * At this point the top_waiter has either taken uaddr2 or is
1510 * waiting on it. If the former, then the pi_state will not 1522 * waiting on it. If the former, then the pi_state will not
1511 * exist yet, look it up one more time to ensure we have a 1523 * exist yet, look it up one more time to ensure we have a
1512 * reference to it. 1524 * reference to it. If the lock was taken, ret contains the
1525 * vpid of the top waiter task.
1513 */ 1526 */
1514 if (ret == 1) { 1527 if (ret > 0) {
1515 WARN_ON(pi_state); 1528 WARN_ON(pi_state);
1516 drop_count++; 1529 drop_count++;
1517 task_count++; 1530 task_count++;
1518 ret = get_futex_value_locked(&curval2, uaddr2); 1531 /*
1519 if (!ret) 1532 * If we acquired the lock, then the user
1520 ret = lookup_pi_state(curval2, hb2, &key2, 1533 * space value of uaddr2 should be vpid. It
1521 &pi_state); 1534 * cannot be changed by the top waiter as it
1535 * is blocked on hb2 lock if it tries to do
1536 * so. If something fiddled with it behind our
1537 * back the pi state lookup might unearth
1538 * it. So we rather use the known value than
1539 * rereading and handing potential crap to
1540 * lookup_pi_state.
1541 */
1542 ret = lookup_pi_state(ret, hb2, &key2, &pi_state, NULL);
1522 } 1543 }
1523 1544
1524 switch (ret) { 1545 switch (ret) {