Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

+24 -21
+24 -21
kernel/futex.c
··· 284 284 drop_futex_key_refs(key); 285 285 } 286 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 + 287 306 /** 288 307 * futex_top_waiter() - Return the highest priority waiter on a futex 289 308 * @hb: the hash bucket the futex_q's reside in ··· 915 896 retry_private: 916 897 op_ret = futex_atomic_op_inuser(op, uaddr2); 917 898 if (unlikely(op_ret < 0)) { 918 - u32 dummy; 919 899 920 900 double_unlock_hb(hb1, hb2); 921 901 ··· 932 914 goto out_put_keys; 933 915 } 934 916 935 - ret = get_user(dummy, uaddr2); 917 + ret = fault_in_user_writeable(uaddr2); 936 918 if (ret) 937 919 goto out_put_keys; 938 920 ··· 1222 1204 double_unlock_hb(hb1, hb2); 1223 1205 put_futex_key(fshared, &key2); 1224 1206 put_futex_key(fshared, &key1); 1225 - ret = get_user(curval2, uaddr2); 1207 + ret = fault_in_user_writeable(uaddr2); 1226 1208 if (!ret) 1227 1209 goto retry; 1228 1210 goto out; ··· 1500 1482 handle_fault: 1501 1483 spin_unlock(q->lock_ptr); 1502 1484 1503 - ret = get_user(uval, uaddr); 1485 + ret = fault_in_user_writeable(uaddr); 1504 1486 1505 1487 spin_lock(q->lock_ptr); 1506 1488 ··· 1825 1807 { 1826 1808 struct hrtimer_sleeper timeout, *to = NULL; 1827 1809 struct futex_hash_bucket *hb; 1828 - u32 uval; 1829 1810 struct futex_q q; 1830 1811 int res, ret; 1831 1812 ··· 1926 1909 return ret != -EINTR ? ret : -ERESTARTNOINTR; 1927 1910 1928 1911 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 1912 queue_unlock(&q, hb); 1937 1913 1938 - ret = get_user(uval, uaddr); 1914 + ret = fault_in_user_writeable(uaddr); 1939 1915 if (ret) 1940 1916 goto out_put_key; 1941 1917 ··· 2023 2013 return ret; 2024 2014 2025 2015 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 2016 spin_unlock(&hb->lock); 2034 2017 put_futex_key(fshared, &key); 2035 2018 2036 - ret = get_user(uval, uaddr); 2019 + ret = fault_in_user_writeable(uaddr); 2037 2020 if (!ret) 2038 2021 goto retry; 2039 2022