Merge branch 'futexes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip

* 'futexes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip:
futex: Fix the write access fault problem for real

Changed files
+24 -21
kernel
+24 -21
kernel/futex.c
··· 284 drop_futex_key_refs(key); 285 } 286 287 /** 288 * futex_top_waiter() - Return the highest priority waiter on a futex 289 * @hb: the hash bucket the futex_q's reside in ··· 915 retry_private: 916 op_ret = futex_atomic_op_inuser(op, uaddr2); 917 if (unlikely(op_ret < 0)) { 918 - u32 dummy; 919 920 double_unlock_hb(hb1, hb2); 921 ··· 932 goto out_put_keys; 933 } 934 935 - ret = get_user(dummy, uaddr2); 936 if (ret) 937 goto out_put_keys; 938 ··· 1222 double_unlock_hb(hb1, hb2); 1223 put_futex_key(fshared, &key2); 1224 put_futex_key(fshared, &key1); 1225 - ret = get_user(curval2, uaddr2); 1226 if (!ret) 1227 goto retry; 1228 goto out; ··· 1500 handle_fault: 1501 spin_unlock(q->lock_ptr); 1502 1503 - ret = get_user(uval, uaddr); 1504 1505 spin_lock(q->lock_ptr); 1506 ··· 1825 { 1826 struct hrtimer_sleeper timeout, *to = NULL; 1827 struct futex_hash_bucket *hb; 1828 - u32 uval; 1829 struct futex_q q; 1830 int res, ret; 1831 ··· 1926 return ret != -EINTR ? ret : -ERESTARTNOINTR; 1927 1928 uaddr_faulted: 1929 - /* 1930 - * We have to r/w *(int __user *)uaddr, and we have to modify it 1931 - * atomically. Therefore, if we continue to fault after get_user() 1932 - * below, we need to handle the fault ourselves, while still holding 1933 - * the mmap_sem. This can occur if the uaddr is under contention as 1934 - * we have to drop the mmap_sem in order to call get_user(). 1935 - */ 1936 queue_unlock(&q, hb); 1937 1938 - ret = get_user(uval, uaddr); 1939 if (ret) 1940 goto out_put_key; 1941 ··· 2023 return ret; 2024 2025 pi_faulted: 2026 - /* 2027 - * We have to r/w *(int __user *)uaddr, and we have to modify it 2028 - * atomically. Therefore, if we continue to fault after get_user() 2029 - * below, we need to handle the fault ourselves, while still holding 2030 - * the mmap_sem. This can occur if the uaddr is under contention as 2031 - * we have to drop the mmap_sem in order to call get_user(). 2032 - */ 2033 spin_unlock(&hb->lock); 2034 put_futex_key(fshared, &key); 2035 2036 - ret = get_user(uval, uaddr); 2037 if (!ret) 2038 goto retry; 2039
··· 284 drop_futex_key_refs(key); 285 } 286 287 + /* 288 + * fault_in_user_writeable - fault in user address and verify RW access 289 + * @uaddr: pointer to faulting user space address 290 + * 291 + * Slow path to fixup the fault we just took in the atomic write 292 + * access to @uaddr. 293 + * 294 + * We have no generic implementation of a non destructive write to the 295 + * user address. We know that we faulted in the atomic pagefault 296 + * disabled section so we can as well avoid the #PF overhead by 297 + * calling get_user_pages() right away. 298 + */ 299 + static int fault_in_user_writeable(u32 __user *uaddr) 300 + { 301 + int ret = get_user_pages(current, current->mm, (unsigned long)uaddr, 302 + sizeof(*uaddr), 1, 0, NULL, NULL); 303 + return ret < 0 ? ret : 0; 304 + } 305 + 306 /** 307 * futex_top_waiter() - Return the highest priority waiter on a futex 308 * @hb: the hash bucket the futex_q's reside in ··· 896 retry_private: 897 op_ret = futex_atomic_op_inuser(op, uaddr2); 898 if (unlikely(op_ret < 0)) { 899 900 double_unlock_hb(hb1, hb2); 901 ··· 914 goto out_put_keys; 915 } 916 917 + ret = fault_in_user_writeable(uaddr2); 918 if (ret) 919 goto out_put_keys; 920 ··· 1204 double_unlock_hb(hb1, hb2); 1205 put_futex_key(fshared, &key2); 1206 put_futex_key(fshared, &key1); 1207 + ret = fault_in_user_writeable(uaddr2); 1208 if (!ret) 1209 goto retry; 1210 goto out; ··· 1482 handle_fault: 1483 spin_unlock(q->lock_ptr); 1484 1485 + ret = fault_in_user_writeable(uaddr); 1486 1487 spin_lock(q->lock_ptr); 1488 ··· 1807 { 1808 struct hrtimer_sleeper timeout, *to = NULL; 1809 struct futex_hash_bucket *hb; 1810 struct futex_q q; 1811 int res, ret; 1812 ··· 1909 return ret != -EINTR ? ret : -ERESTARTNOINTR; 1910 1911 uaddr_faulted: 1912 queue_unlock(&q, hb); 1913 1914 + ret = fault_in_user_writeable(uaddr); 1915 if (ret) 1916 goto out_put_key; 1917 ··· 2013 return ret; 2014 2015 pi_faulted: 2016 spin_unlock(&hb->lock); 2017 put_futex_key(fshared, &key); 2018 2019 + ret = fault_in_user_writeable(uaddr); 2020 if (!ret) 2021 goto retry; 2022