diff options
| -rw-r--r-- | kernel/futex.c | 47 |
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 | ||
| 746 | static int | 746 | static int |
| 747 | lookup_pi_state(u32 uval, struct futex_hash_bucket *hb, | 747 | lookup_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 | */ |
| 1353 | static int futex_proxy_trylock_atomic(u32 __user *pifutex, | 1364 | static 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) { |
