Loading kernel/futex.c +24 −21 Original line number Diff line number Diff line Loading @@ -284,6 +284,25 @@ void put_futex_key(int fshared, union futex_key *key) drop_futex_key_refs(key); } /* * fault_in_user_writeable - fault in user address and verify RW access * @uaddr: pointer to faulting user space address * * Slow path to fixup the fault we just took in the atomic write * access to @uaddr. * * We have no generic implementation of a non destructive write to the * user address. We know that we faulted in the atomic pagefault * disabled section so we can as well avoid the #PF overhead by * calling get_user_pages() right away. */ static int fault_in_user_writeable(u32 __user *uaddr) { int ret = get_user_pages(current, current->mm, (unsigned long)uaddr, sizeof(*uaddr), 1, 0, NULL, NULL); return ret < 0 ? ret : 0; } /** * futex_top_waiter() - Return the highest priority waiter on a futex * @hb: the hash bucket the futex_q's reside in Loading Loading @@ -896,7 +915,6 @@ futex_wake_op(u32 __user *uaddr1, int fshared, u32 __user *uaddr2, retry_private: op_ret = futex_atomic_op_inuser(op, uaddr2); if (unlikely(op_ret < 0)) { u32 dummy; double_unlock_hb(hb1, hb2); Loading @@ -914,7 +932,7 @@ futex_wake_op(u32 __user *uaddr1, int fshared, u32 __user *uaddr2, goto out_put_keys; } ret = get_user(dummy, uaddr2); ret = fault_in_user_writeable(uaddr2); if (ret) goto out_put_keys; Loading Loading @@ -1204,7 +1222,7 @@ static int futex_requeue(u32 __user *uaddr1, int fshared, u32 __user *uaddr2, double_unlock_hb(hb1, hb2); put_futex_key(fshared, &key2); put_futex_key(fshared, &key1); ret = get_user(curval2, uaddr2); ret = fault_in_user_writeable(uaddr2); if (!ret) goto retry; goto out; Loading Loading @@ -1482,7 +1500,7 @@ static int fixup_pi_state_owner(u32 __user *uaddr, struct futex_q *q, handle_fault: spin_unlock(q->lock_ptr); ret = get_user(uval, uaddr); ret = fault_in_user_writeable(uaddr); spin_lock(q->lock_ptr); Loading Loading @@ -1807,7 +1825,6 @@ static int futex_lock_pi(u32 __user *uaddr, int fshared, { struct hrtimer_sleeper timeout, *to = NULL; struct futex_hash_bucket *hb; u32 uval; struct futex_q q; int res, ret; Loading Loading @@ -1909,16 +1926,9 @@ static int futex_lock_pi(u32 __user *uaddr, int fshared, return ret != -EINTR ? ret : -ERESTARTNOINTR; uaddr_faulted: /* * We have to r/w *(int __user *)uaddr, and we have to modify it * atomically. Therefore, if we continue to fault after get_user() * below, we need to handle the fault ourselves, while still holding * the mmap_sem. This can occur if the uaddr is under contention as * we have to drop the mmap_sem in order to call get_user(). */ queue_unlock(&q, hb); ret = get_user(uval, uaddr); ret = fault_in_user_writeable(uaddr); if (ret) goto out_put_key; Loading Loading @@ -2013,17 +2023,10 @@ static int futex_unlock_pi(u32 __user *uaddr, int fshared) return ret; pi_faulted: /* * We have to r/w *(int __user *)uaddr, and we have to modify it * atomically. Therefore, if we continue to fault after get_user() * below, we need to handle the fault ourselves, while still holding * the mmap_sem. This can occur if the uaddr is under contention as * we have to drop the mmap_sem in order to call get_user(). */ spin_unlock(&hb->lock); put_futex_key(fshared, &key); ret = get_user(uval, uaddr); ret = fault_in_user_writeable(uaddr); if (!ret) goto retry; Loading Loading
kernel/futex.c +24 −21 Original line number Diff line number Diff line Loading @@ -284,6 +284,25 @@ void put_futex_key(int fshared, union futex_key *key) drop_futex_key_refs(key); } /* * fault_in_user_writeable - fault in user address and verify RW access * @uaddr: pointer to faulting user space address * * Slow path to fixup the fault we just took in the atomic write * access to @uaddr. * * We have no generic implementation of a non destructive write to the * user address. We know that we faulted in the atomic pagefault * disabled section so we can as well avoid the #PF overhead by * calling get_user_pages() right away. */ static int fault_in_user_writeable(u32 __user *uaddr) { int ret = get_user_pages(current, current->mm, (unsigned long)uaddr, sizeof(*uaddr), 1, 0, NULL, NULL); return ret < 0 ? ret : 0; } /** * futex_top_waiter() - Return the highest priority waiter on a futex * @hb: the hash bucket the futex_q's reside in Loading Loading @@ -896,7 +915,6 @@ futex_wake_op(u32 __user *uaddr1, int fshared, u32 __user *uaddr2, retry_private: op_ret = futex_atomic_op_inuser(op, uaddr2); if (unlikely(op_ret < 0)) { u32 dummy; double_unlock_hb(hb1, hb2); Loading @@ -914,7 +932,7 @@ futex_wake_op(u32 __user *uaddr1, int fshared, u32 __user *uaddr2, goto out_put_keys; } ret = get_user(dummy, uaddr2); ret = fault_in_user_writeable(uaddr2); if (ret) goto out_put_keys; Loading Loading @@ -1204,7 +1222,7 @@ static int futex_requeue(u32 __user *uaddr1, int fshared, u32 __user *uaddr2, double_unlock_hb(hb1, hb2); put_futex_key(fshared, &key2); put_futex_key(fshared, &key1); ret = get_user(curval2, uaddr2); ret = fault_in_user_writeable(uaddr2); if (!ret) goto retry; goto out; Loading Loading @@ -1482,7 +1500,7 @@ static int fixup_pi_state_owner(u32 __user *uaddr, struct futex_q *q, handle_fault: spin_unlock(q->lock_ptr); ret = get_user(uval, uaddr); ret = fault_in_user_writeable(uaddr); spin_lock(q->lock_ptr); Loading Loading @@ -1807,7 +1825,6 @@ static int futex_lock_pi(u32 __user *uaddr, int fshared, { struct hrtimer_sleeper timeout, *to = NULL; struct futex_hash_bucket *hb; u32 uval; struct futex_q q; int res, ret; Loading Loading @@ -1909,16 +1926,9 @@ static int futex_lock_pi(u32 __user *uaddr, int fshared, return ret != -EINTR ? ret : -ERESTARTNOINTR; uaddr_faulted: /* * We have to r/w *(int __user *)uaddr, and we have to modify it * atomically. Therefore, if we continue to fault after get_user() * below, we need to handle the fault ourselves, while still holding * the mmap_sem. This can occur if the uaddr is under contention as * we have to drop the mmap_sem in order to call get_user(). */ queue_unlock(&q, hb); ret = get_user(uval, uaddr); ret = fault_in_user_writeable(uaddr); if (ret) goto out_put_key; Loading Loading @@ -2013,17 +2023,10 @@ static int futex_unlock_pi(u32 __user *uaddr, int fshared) return ret; pi_faulted: /* * We have to r/w *(int __user *)uaddr, and we have to modify it * atomically. Therefore, if we continue to fault after get_user() * below, we need to handle the fault ourselves, while still holding * the mmap_sem. This can occur if the uaddr is under contention as * we have to drop the mmap_sem in order to call get_user(). */ spin_unlock(&hb->lock); put_futex_key(fshared, &key); ret = get_user(uval, uaddr); ret = fault_in_user_writeable(uaddr); if (!ret) goto retry; Loading