diff options
| -rw-r--r-- | kernel/futex.c | 83 |
1 files changed, 4 insertions, 79 deletions
diff --git a/kernel/futex.c b/kernel/futex.c index a4c39fa0a7a3..6a726684217e 100644 --- a/kernel/futex.c +++ b/kernel/futex.c | |||
| @@ -123,24 +123,6 @@ struct futex_hash_bucket { | |||
| 123 | static struct futex_hash_bucket futex_queues[1<<FUTEX_HASHBITS]; | 123 | static struct futex_hash_bucket futex_queues[1<<FUTEX_HASHBITS]; |
| 124 | 124 | ||
| 125 | /* | 125 | /* |
| 126 | * Take mm->mmap_sem, when futex is shared | ||
| 127 | */ | ||
| 128 | static inline void futex_lock_mm(struct rw_semaphore *fshared) | ||
| 129 | { | ||
| 130 | if (fshared) | ||
| 131 | down_read(fshared); | ||
| 132 | } | ||
| 133 | |||
| 134 | /* | ||
| 135 | * Release mm->mmap_sem, when the futex is shared | ||
| 136 | */ | ||
| 137 | static inline void futex_unlock_mm(struct rw_semaphore *fshared) | ||
| 138 | { | ||
| 139 | if (fshared) | ||
| 140 | up_read(fshared); | ||
| 141 | } | ||
| 142 | |||
| 143 | /* | ||
| 144 | * We hash on the keys returned from get_futex_key (see below). | 126 | * We hash on the keys returned from get_futex_key (see below). |
| 145 | */ | 127 | */ |
| 146 | static struct futex_hash_bucket *hash_futex(union futex_key *key) | 128 | static struct futex_hash_bucket *hash_futex(union futex_key *key) |
| @@ -250,7 +232,9 @@ static int get_futex_key(u32 __user *uaddr, struct rw_semaphore *fshared, | |||
| 250 | } | 232 | } |
| 251 | 233 | ||
| 252 | again: | 234 | again: |
| 235 | down_read(&mm->mmap_sem); | ||
| 253 | err = get_user_pages(current, mm, address, 1, 0, 0, &page, NULL); | 236 | err = get_user_pages(current, mm, address, 1, 0, 0, &page, NULL); |
| 237 | up_read(&mm->mmap_sem); | ||
| 254 | if (err < 0) | 238 | if (err < 0) |
| 255 | return err; | 239 | return err; |
| 256 | 240 | ||
| @@ -327,8 +311,7 @@ static int futex_handle_fault(unsigned long address, | |||
| 327 | if (attempt > 2) | 311 | if (attempt > 2) |
| 328 | return ret; | 312 | return ret; |
| 329 | 313 | ||
| 330 | if (!fshared) | 314 | down_read(&mm->mmap_sem); |
| 331 | down_read(&mm->mmap_sem); | ||
| 332 | vma = find_vma(mm, address); | 315 | vma = find_vma(mm, address); |
| 333 | if (vma && address >= vma->vm_start && | 316 | if (vma && address >= vma->vm_start && |
| 334 | (vma->vm_flags & VM_WRITE)) { | 317 | (vma->vm_flags & VM_WRITE)) { |
| @@ -348,8 +331,7 @@ static int futex_handle_fault(unsigned long address, | |||
| 348 | current->min_flt++; | 331 | current->min_flt++; |
| 349 | } | 332 | } |
| 350 | } | 333 | } |
| 351 | if (!fshared) | 334 | up_read(&mm->mmap_sem); |
| 352 | up_read(&mm->mmap_sem); | ||
| 353 | return ret; | 335 | return ret; |
| 354 | } | 336 | } |
| 355 | 337 | ||
| @@ -719,8 +701,6 @@ static int futex_wake(u32 __user *uaddr, struct rw_semaphore *fshared, | |||
| 719 | if (!bitset) | 701 | if (!bitset) |
| 720 | return -EINVAL; | 702 | return -EINVAL; |
| 721 | 703 | ||
| 722 | futex_lock_mm(fshared); | ||
| 723 | |||
| 724 | ret = get_futex_key(uaddr, fshared, &key); | 704 | ret = get_futex_key(uaddr, fshared, &key); |
| 725 | if (unlikely(ret != 0)) | 705 | if (unlikely(ret != 0)) |
| 726 | goto out; | 706 | goto out; |
| @@ -749,7 +729,6 @@ static int futex_wake(u32 __user *uaddr, struct rw_semaphore *fshared, | |||
| 749 | spin_unlock(&hb->lock); | 729 | spin_unlock(&hb->lock); |
| 750 | out: | 730 | out: |
| 751 | put_futex_key(fshared, &key); | 731 | put_futex_key(fshared, &key); |
| 752 | futex_unlock_mm(fshared); | ||
| 753 | return ret; | 732 | return ret; |
| 754 | } | 733 | } |
| 755 | 734 | ||
| @@ -769,8 +748,6 @@ futex_wake_op(u32 __user *uaddr1, struct rw_semaphore *fshared, | |||
| 769 | int ret, op_ret, attempt = 0; | 748 | int ret, op_ret, attempt = 0; |
| 770 | 749 | ||
| 771 | retryfull: | 750 | retryfull: |
| 772 | futex_lock_mm(fshared); | ||
| 773 | |||
| 774 | ret = get_futex_key(uaddr1, fshared, &key1); | 751 | ret = get_futex_key(uaddr1, fshared, &key1); |
| 775 | if (unlikely(ret != 0)) | 752 | if (unlikely(ret != 0)) |
| 776 | goto out; | 753 | goto out; |
| @@ -821,12 +798,6 @@ retry: | |||
| 821 | goto retry; | 798 | goto retry; |
| 822 | } | 799 | } |
| 823 | 800 | ||
| 824 | /* | ||
| 825 | * If we would have faulted, release mmap_sem, | ||
| 826 | * fault it in and start all over again. | ||
| 827 | */ | ||
| 828 | futex_unlock_mm(fshared); | ||
| 829 | |||
| 830 | ret = get_user(dummy, uaddr2); | 801 | ret = get_user(dummy, uaddr2); |
| 831 | if (ret) | 802 | if (ret) |
| 832 | return ret; | 803 | return ret; |
| @@ -864,7 +835,6 @@ retry: | |||
| 864 | out: | 835 | out: |
| 865 | put_futex_key(fshared, &key2); | 836 | put_futex_key(fshared, &key2); |
| 866 | put_futex_key(fshared, &key1); | 837 | put_futex_key(fshared, &key1); |
| 867 | futex_unlock_mm(fshared); | ||
| 868 | 838 | ||
| 869 | return ret; | 839 | return ret; |
| 870 | } | 840 | } |
| @@ -884,8 +854,6 @@ static int futex_requeue(u32 __user *uaddr1, struct rw_semaphore *fshared, | |||
| 884 | int ret, drop_count = 0; | 854 | int ret, drop_count = 0; |
| 885 | 855 | ||
| 886 | retry: | 856 | retry: |
| 887 | futex_lock_mm(fshared); | ||
| 888 | |||
| 889 | ret = get_futex_key(uaddr1, fshared, &key1); | 857 | ret = get_futex_key(uaddr1, fshared, &key1); |
| 890 | if (unlikely(ret != 0)) | 858 | if (unlikely(ret != 0)) |
| 891 | goto out; | 859 | goto out; |
| @@ -908,12 +876,6 @@ static int futex_requeue(u32 __user *uaddr1, struct rw_semaphore *fshared, | |||
| 908 | if (hb1 != hb2) | 876 | if (hb1 != hb2) |
| 909 | spin_unlock(&hb2->lock); | 877 | spin_unlock(&hb2->lock); |
| 910 | 878 | ||
| 911 | /* | ||
| 912 | * If we would have faulted, release mmap_sem, fault | ||
| 913 | * it in and start all over again. | ||
| 914 | */ | ||
| 915 | futex_unlock_mm(fshared); | ||
| 916 | |||
| 917 | ret = get_user(curval, uaddr1); | 879 | ret = get_user(curval, uaddr1); |
| 918 | 880 | ||
| 919 | if (!ret) | 881 | if (!ret) |
| @@ -967,7 +929,6 @@ out_unlock: | |||
| 967 | out: | 929 | out: |
| 968 | put_futex_key(fshared, &key2); | 930 | put_futex_key(fshared, &key2); |
| 969 | put_futex_key(fshared, &key1); | 931 | put_futex_key(fshared, &key1); |
| 970 | futex_unlock_mm(fshared); | ||
| 971 | return ret; | 932 | return ret; |
| 972 | } | 933 | } |
| 973 | 934 | ||
| @@ -1211,8 +1172,6 @@ static int futex_wait(u32 __user *uaddr, struct rw_semaphore *fshared, | |||
| 1211 | q.pi_state = NULL; | 1172 | q.pi_state = NULL; |
| 1212 | q.bitset = bitset; | 1173 | q.bitset = bitset; |
| 1213 | retry: | 1174 | retry: |
| 1214 | futex_lock_mm(fshared); | ||
| 1215 | |||
| 1216 | q.key = FUTEX_KEY_INIT; | 1175 | q.key = FUTEX_KEY_INIT; |
| 1217 | ret = get_futex_key(uaddr, fshared, &q.key); | 1176 | ret = get_futex_key(uaddr, fshared, &q.key); |
| 1218 | if (unlikely(ret != 0)) | 1177 | if (unlikely(ret != 0)) |
| @@ -1245,12 +1204,6 @@ static int futex_wait(u32 __user *uaddr, struct rw_semaphore *fshared, | |||
| 1245 | if (unlikely(ret)) { | 1204 | if (unlikely(ret)) { |
| 1246 | queue_unlock(&q, hb); | 1205 | queue_unlock(&q, hb); |
| 1247 | 1206 | ||
| 1248 | /* | ||
| 1249 | * If we would have faulted, release mmap_sem, fault it in and | ||
| 1250 | * start all over again. | ||
| 1251 | */ | ||
| 1252 | futex_unlock_mm(fshared); | ||
| 1253 | |||
| 1254 | ret = get_user(uval, uaddr); | 1207 | ret = get_user(uval, uaddr); |
| 1255 | 1208 | ||
| 1256 | if (!ret) | 1209 | if (!ret) |
| @@ -1265,12 +1218,6 @@ static int futex_wait(u32 __user *uaddr, struct rw_semaphore *fshared, | |||
| 1265 | queue_me(&q, hb); | 1218 | queue_me(&q, hb); |
| 1266 | 1219 | ||
| 1267 | /* | 1220 | /* |
| 1268 | * Now the futex is queued and we have checked the data, we | ||
| 1269 | * don't want to hold mmap_sem while we sleep. | ||
| 1270 | */ | ||
| 1271 | futex_unlock_mm(fshared); | ||
| 1272 | |||
| 1273 | /* | ||
| 1274 | * There might have been scheduling since the queue_me(), as we | 1221 | * There might have been scheduling since the queue_me(), as we |
| 1275 | * cannot hold a spinlock across the get_user() in case it | 1222 | * cannot hold a spinlock across the get_user() in case it |
| 1276 | * faults, and we cannot just set TASK_INTERRUPTIBLE state when | 1223 | * faults, and we cannot just set TASK_INTERRUPTIBLE state when |
| @@ -1355,7 +1302,6 @@ static int futex_wait(u32 __user *uaddr, struct rw_semaphore *fshared, | |||
| 1355 | 1302 | ||
| 1356 | out_release_sem: | 1303 | out_release_sem: |
| 1357 | put_futex_key(fshared, &q.key); | 1304 | put_futex_key(fshared, &q.key); |
| 1358 | futex_unlock_mm(fshared); | ||
| 1359 | return ret; | 1305 | return ret; |
| 1360 | } | 1306 | } |
| 1361 | 1307 | ||
| @@ -1404,8 +1350,6 @@ static int futex_lock_pi(u32 __user *uaddr, struct rw_semaphore *fshared, | |||
| 1404 | 1350 | ||
| 1405 | q.pi_state = NULL; | 1351 | q.pi_state = NULL; |
| 1406 | retry: | 1352 | retry: |
| 1407 | futex_lock_mm(fshared); | ||
| 1408 | |||
| 1409 | q.key = FUTEX_KEY_INIT; | 1353 | q.key = FUTEX_KEY_INIT; |
| 1410 | ret = get_futex_key(uaddr, fshared, &q.key); | 1354 | ret = get_futex_key(uaddr, fshared, &q.key); |
| 1411 | if (unlikely(ret != 0)) | 1355 | if (unlikely(ret != 0)) |
| @@ -1495,7 +1439,6 @@ static int futex_lock_pi(u32 __user *uaddr, struct rw_semaphore *fshared, | |||
| 1495 | * exit to complete. | 1439 | * exit to complete. |
| 1496 | */ | 1440 | */ |
| 1497 | queue_unlock(&q, hb); | 1441 | queue_unlock(&q, hb); |
| 1498 | futex_unlock_mm(fshared); | ||
| 1499 | cond_resched(); | 1442 | cond_resched(); |
| 1500 | goto retry; | 1443 | goto retry; |
| 1501 | 1444 | ||
| @@ -1527,12 +1470,6 @@ static int futex_lock_pi(u32 __user *uaddr, struct rw_semaphore *fshared, | |||
| 1527 | */ | 1470 | */ |
| 1528 | queue_me(&q, hb); | 1471 | queue_me(&q, hb); |
| 1529 | 1472 | ||
| 1530 | /* | ||
| 1531 | * Now the futex is queued and we have checked the data, we | ||
| 1532 | * don't want to hold mmap_sem while we sleep. | ||
| 1533 | */ | ||
| 1534 | futex_unlock_mm(fshared); | ||
| 1535 | |||
| 1536 | WARN_ON(!q.pi_state); | 1473 | WARN_ON(!q.pi_state); |
| 1537 | /* | 1474 | /* |
| 1538 | * Block on the PI mutex: | 1475 | * Block on the PI mutex: |
| @@ -1545,7 +1482,6 @@ static int futex_lock_pi(u32 __user *uaddr, struct rw_semaphore *fshared, | |||
| 1545 | ret = ret ? 0 : -EWOULDBLOCK; | 1482 | ret = ret ? 0 : -EWOULDBLOCK; |
| 1546 | } | 1483 | } |
| 1547 | 1484 | ||
| 1548 | futex_lock_mm(fshared); | ||
| 1549 | spin_lock(q.lock_ptr); | 1485 | spin_lock(q.lock_ptr); |
| 1550 | 1486 | ||
| 1551 | if (!ret) { | 1487 | if (!ret) { |
| @@ -1611,7 +1547,6 @@ static int futex_lock_pi(u32 __user *uaddr, struct rw_semaphore *fshared, | |||
| 1611 | 1547 | ||
| 1612 | /* Unqueue and drop the lock */ | 1548 | /* Unqueue and drop the lock */ |
| 1613 | unqueue_me_pi(&q); | 1549 | unqueue_me_pi(&q); |
| 1614 | futex_unlock_mm(fshared); | ||
| 1615 | 1550 | ||
| 1616 | if (to) | 1551 | if (to) |
| 1617 | destroy_hrtimer_on_stack(&to->timer); | 1552 | destroy_hrtimer_on_stack(&to->timer); |
| @@ -1622,7 +1557,6 @@ static int futex_lock_pi(u32 __user *uaddr, struct rw_semaphore *fshared, | |||
| 1622 | 1557 | ||
| 1623 | out_release_sem: | 1558 | out_release_sem: |
| 1624 | put_futex_key(fshared, &q.key); | 1559 | put_futex_key(fshared, &q.key); |
| 1625 | futex_unlock_mm(fshared); | ||
| 1626 | if (to) | 1560 | if (to) |
| 1627 | destroy_hrtimer_on_stack(&to->timer); | 1561 | destroy_hrtimer_on_stack(&to->timer); |
| 1628 | return ret; | 1562 | return ret; |
| @@ -1646,8 +1580,6 @@ static int futex_lock_pi(u32 __user *uaddr, struct rw_semaphore *fshared, | |||
| 1646 | goto retry_unlocked; | 1580 | goto retry_unlocked; |
| 1647 | } | 1581 | } |
| 1648 | 1582 | ||
| 1649 | futex_unlock_mm(fshared); | ||
| 1650 | |||
| 1651 | ret = get_user(uval, uaddr); | 1583 | ret = get_user(uval, uaddr); |
| 1652 | if (!ret && (uval != -EFAULT)) | 1584 | if (!ret && (uval != -EFAULT)) |
| 1653 | goto retry; | 1585 | goto retry; |
| @@ -1679,10 +1611,6 @@ retry: | |||
| 1679 | */ | 1611 | */ |
| 1680 | if ((uval & FUTEX_TID_MASK) != task_pid_vnr(current)) | 1612 | if ((uval & FUTEX_TID_MASK) != task_pid_vnr(current)) |
| 1681 | return -EPERM; | 1613 | return -EPERM; |
| 1682 | /* | ||
| 1683 | * First take all the futex related locks: | ||
| 1684 | */ | ||
| 1685 | futex_lock_mm(fshared); | ||
| 1686 | 1614 | ||
| 1687 | ret = get_futex_key(uaddr, fshared, &key); | 1615 | ret = get_futex_key(uaddr, fshared, &key); |
| 1688 | if (unlikely(ret != 0)) | 1616 | if (unlikely(ret != 0)) |
| @@ -1742,7 +1670,6 @@ out_unlock: | |||
| 1742 | spin_unlock(&hb->lock); | 1670 | spin_unlock(&hb->lock); |
| 1743 | out: | 1671 | out: |
| 1744 | put_futex_key(fshared, &key); | 1672 | put_futex_key(fshared, &key); |
| 1745 | futex_unlock_mm(fshared); | ||
| 1746 | 1673 | ||
| 1747 | return ret; | 1674 | return ret; |
| 1748 | 1675 | ||
| @@ -1766,8 +1693,6 @@ pi_faulted: | |||
| 1766 | goto retry_unlocked; | 1693 | goto retry_unlocked; |
| 1767 | } | 1694 | } |
| 1768 | 1695 | ||
| 1769 | futex_unlock_mm(fshared); | ||
| 1770 | |||
| 1771 | ret = get_user(uval, uaddr); | 1696 | ret = get_user(uval, uaddr); |
| 1772 | if (!ret && (uval != -EFAULT)) | 1697 | if (!ret && (uval != -EFAULT)) |
| 1773 | goto retry; | 1698 | goto retry; |
