Loading kernel/futex.c +46 −63 Original line number Diff line number Diff line Loading @@ -1032,7 +1032,8 @@ void exit_pi_state_list(struct task_struct *curr) * FUTEX_OWNER_DIED bit. See [4] * * [10] There is no transient state which leaves owner and user space * TID out of sync. * TID out of sync. Except one error case where the kernel is denied * write access to the user address, see fixup_pi_state_owner(). * * * Serialization and lifetime rules: Loading Loading @@ -2373,18 +2374,13 @@ static void unqueue_me_pi(struct futex_q *q) spin_unlock(q->lock_ptr); } static int fixup_pi_state_owner(u32 __user *uaddr, struct futex_q *q, static int __fixup_pi_state_owner(u32 __user *uaddr, struct futex_q *q, struct task_struct *argowner) { u32 uval, uninitialized_var(curval), newval, newtid; struct futex_pi_state *pi_state = q->pi_state; u32 uval, uninitialized_var(curval), newval; struct task_struct *oldowner, *newowner; u32 newtid; int ret, err = 0; lockdep_assert_held(q->lock_ptr); raw_spin_lock_irq(&pi_state->pi_mutex.wait_lock); int err = 0; oldowner = pi_state->owner; Loading Loading @@ -2418,14 +2414,12 @@ static int fixup_pi_state_owner(u32 __user *uaddr, struct futex_q *q, * We raced against a concurrent self; things are * already fixed up. Nothing to do. */ ret = 0; goto out_unlock; return 0; } if (__rt_mutex_futex_trylock(&pi_state->pi_mutex)) { /* We got the lock. pi_state is correct. Tell caller. */ ret = 1; goto out_unlock; return 1; } /* Loading @@ -2452,8 +2446,7 @@ static int fixup_pi_state_owner(u32 __user *uaddr, struct futex_q *q, * We raced against a concurrent self; things are * already fixed up. Nothing to do. */ ret = 1; goto out_unlock; return 1; } newowner = argowner; } Loading Loading @@ -2484,7 +2477,6 @@ static int fixup_pi_state_owner(u32 __user *uaddr, struct futex_q *q, * itself. */ pi_state_update_owner(pi_state, newowner); raw_spin_unlock_irq(&pi_state->pi_mutex.wait_lock); return argowner == current; Loading @@ -2507,17 +2499,16 @@ static int fixup_pi_state_owner(u32 __user *uaddr, struct futex_q *q, switch (err) { case -EFAULT: ret = fault_in_user_writeable(uaddr); err = fault_in_user_writeable(uaddr); break; case -EAGAIN: cond_resched(); ret = 0; err = 0; break; default: WARN_ON_ONCE(1); ret = err; break; } Loading @@ -2527,17 +2518,44 @@ static int fixup_pi_state_owner(u32 __user *uaddr, struct futex_q *q, /* * Check if someone else fixed it for us: */ if (pi_state->owner != oldowner) { ret = argowner == current; goto out_unlock; if (pi_state->owner != oldowner) return argowner == current; /* Retry if err was -EAGAIN or the fault in succeeded */ if (!err) goto retry; /* * fault_in_user_writeable() failed so user state is immutable. At * best we can make the kernel state consistent but user state will * be most likely hosed and any subsequent unlock operation will be * rejected due to PI futex rule [10]. * * Ensure that the rtmutex owner is also the pi_state owner despite * the user space value claiming something different. There is no * point in unlocking the rtmutex if current is the owner as it * would need to wait until the next waiter has taken the rtmutex * to guarantee consistent state. Keep it simple. Userspace asked * for this wreckaged state. * * The rtmutex has an owner - either current or some other * task. See the EAGAIN loop above. */ pi_state_update_owner(pi_state, rt_mutex_owner(&pi_state->pi_mutex)); return err; } if (ret) goto out_unlock; static int fixup_pi_state_owner(u32 __user *uaddr, struct futex_q *q, struct task_struct *argowner) { struct futex_pi_state *pi_state = q->pi_state; int ret; goto retry; lockdep_assert_held(q->lock_ptr); out_unlock: raw_spin_lock_irq(&pi_state->pi_mutex.wait_lock); ret = __fixup_pi_state_owner(uaddr, q, argowner); raw_spin_unlock_irq(&pi_state->pi_mutex.wait_lock); return ret; } Loading Loading @@ -2814,7 +2832,6 @@ static int futex_lock_pi(u32 __user *uaddr, unsigned int flags, ktime_t *time, int trylock) { struct hrtimer_sleeper timeout, *to = NULL; struct futex_pi_state *pi_state = NULL; struct rt_mutex_waiter rt_waiter; struct futex_hash_bucket *hb; struct futex_q q = futex_q_init; Loading Loading @@ -2948,23 +2965,9 @@ static int futex_lock_pi(u32 __user *uaddr, unsigned int flags, if (res) ret = (res < 0) ? res : 0; /* * If fixup_owner() faulted and was unable to handle the fault, unlock * it and return the fault to userspace. */ if (ret && (rt_mutex_owner(&q.pi_state->pi_mutex) == current)) { pi_state = q.pi_state; get_pi_state(pi_state); } /* Unqueue and drop the lock */ unqueue_me_pi(&q); if (pi_state) { rt_mutex_futex_unlock(&pi_state->pi_mutex); put_pi_state(pi_state); } goto out_put_key; out_unlock_put_key: Loading Loading @@ -3230,7 +3233,6 @@ static int futex_wait_requeue_pi(u32 __user *uaddr, unsigned int flags, u32 __user *uaddr2) { struct hrtimer_sleeper timeout, *to = NULL; struct futex_pi_state *pi_state = NULL; struct rt_mutex_waiter rt_waiter; struct futex_hash_bucket *hb; union futex_key key2 = FUTEX_KEY_INIT; Loading Loading @@ -3315,10 +3317,6 @@ static int futex_wait_requeue_pi(u32 __user *uaddr, unsigned int flags, if (q.pi_state && (q.pi_state->owner != current)) { spin_lock(q.lock_ptr); ret = fixup_pi_state_owner(uaddr2, &q, current); if (ret < 0 && rt_mutex_owner(&q.pi_state->pi_mutex) == current) { pi_state = q.pi_state; get_pi_state(pi_state); } /* * Drop the reference to the pi state which * the requeue_pi() code acquired for us. Loading Loading @@ -3360,25 +3358,10 @@ static int futex_wait_requeue_pi(u32 __user *uaddr, unsigned int flags, if (res) ret = (res < 0) ? res : 0; /* * If fixup_pi_state_owner() faulted and was unable to handle * the fault, unlock the rt_mutex and return the fault to * userspace. */ if (ret && rt_mutex_owner(&q.pi_state->pi_mutex) == current) { pi_state = q.pi_state; get_pi_state(pi_state); } /* Unqueue and drop the lock. */ unqueue_me_pi(&q); } if (pi_state) { rt_mutex_futex_unlock(&pi_state->pi_mutex); put_pi_state(pi_state); } if (ret == -EINTR) { /* * We've already been requeued, but cannot restart by calling Loading Loading
kernel/futex.c +46 −63 Original line number Diff line number Diff line Loading @@ -1032,7 +1032,8 @@ void exit_pi_state_list(struct task_struct *curr) * FUTEX_OWNER_DIED bit. See [4] * * [10] There is no transient state which leaves owner and user space * TID out of sync. * TID out of sync. Except one error case where the kernel is denied * write access to the user address, see fixup_pi_state_owner(). * * * Serialization and lifetime rules: Loading Loading @@ -2373,18 +2374,13 @@ static void unqueue_me_pi(struct futex_q *q) spin_unlock(q->lock_ptr); } static int fixup_pi_state_owner(u32 __user *uaddr, struct futex_q *q, static int __fixup_pi_state_owner(u32 __user *uaddr, struct futex_q *q, struct task_struct *argowner) { u32 uval, uninitialized_var(curval), newval, newtid; struct futex_pi_state *pi_state = q->pi_state; u32 uval, uninitialized_var(curval), newval; struct task_struct *oldowner, *newowner; u32 newtid; int ret, err = 0; lockdep_assert_held(q->lock_ptr); raw_spin_lock_irq(&pi_state->pi_mutex.wait_lock); int err = 0; oldowner = pi_state->owner; Loading Loading @@ -2418,14 +2414,12 @@ static int fixup_pi_state_owner(u32 __user *uaddr, struct futex_q *q, * We raced against a concurrent self; things are * already fixed up. Nothing to do. */ ret = 0; goto out_unlock; return 0; } if (__rt_mutex_futex_trylock(&pi_state->pi_mutex)) { /* We got the lock. pi_state is correct. Tell caller. */ ret = 1; goto out_unlock; return 1; } /* Loading @@ -2452,8 +2446,7 @@ static int fixup_pi_state_owner(u32 __user *uaddr, struct futex_q *q, * We raced against a concurrent self; things are * already fixed up. Nothing to do. */ ret = 1; goto out_unlock; return 1; } newowner = argowner; } Loading Loading @@ -2484,7 +2477,6 @@ static int fixup_pi_state_owner(u32 __user *uaddr, struct futex_q *q, * itself. */ pi_state_update_owner(pi_state, newowner); raw_spin_unlock_irq(&pi_state->pi_mutex.wait_lock); return argowner == current; Loading @@ -2507,17 +2499,16 @@ static int fixup_pi_state_owner(u32 __user *uaddr, struct futex_q *q, switch (err) { case -EFAULT: ret = fault_in_user_writeable(uaddr); err = fault_in_user_writeable(uaddr); break; case -EAGAIN: cond_resched(); ret = 0; err = 0; break; default: WARN_ON_ONCE(1); ret = err; break; } Loading @@ -2527,17 +2518,44 @@ static int fixup_pi_state_owner(u32 __user *uaddr, struct futex_q *q, /* * Check if someone else fixed it for us: */ if (pi_state->owner != oldowner) { ret = argowner == current; goto out_unlock; if (pi_state->owner != oldowner) return argowner == current; /* Retry if err was -EAGAIN or the fault in succeeded */ if (!err) goto retry; /* * fault_in_user_writeable() failed so user state is immutable. At * best we can make the kernel state consistent but user state will * be most likely hosed and any subsequent unlock operation will be * rejected due to PI futex rule [10]. * * Ensure that the rtmutex owner is also the pi_state owner despite * the user space value claiming something different. There is no * point in unlocking the rtmutex if current is the owner as it * would need to wait until the next waiter has taken the rtmutex * to guarantee consistent state. Keep it simple. Userspace asked * for this wreckaged state. * * The rtmutex has an owner - either current or some other * task. See the EAGAIN loop above. */ pi_state_update_owner(pi_state, rt_mutex_owner(&pi_state->pi_mutex)); return err; } if (ret) goto out_unlock; static int fixup_pi_state_owner(u32 __user *uaddr, struct futex_q *q, struct task_struct *argowner) { struct futex_pi_state *pi_state = q->pi_state; int ret; goto retry; lockdep_assert_held(q->lock_ptr); out_unlock: raw_spin_lock_irq(&pi_state->pi_mutex.wait_lock); ret = __fixup_pi_state_owner(uaddr, q, argowner); raw_spin_unlock_irq(&pi_state->pi_mutex.wait_lock); return ret; } Loading Loading @@ -2814,7 +2832,6 @@ static int futex_lock_pi(u32 __user *uaddr, unsigned int flags, ktime_t *time, int trylock) { struct hrtimer_sleeper timeout, *to = NULL; struct futex_pi_state *pi_state = NULL; struct rt_mutex_waiter rt_waiter; struct futex_hash_bucket *hb; struct futex_q q = futex_q_init; Loading Loading @@ -2948,23 +2965,9 @@ static int futex_lock_pi(u32 __user *uaddr, unsigned int flags, if (res) ret = (res < 0) ? res : 0; /* * If fixup_owner() faulted and was unable to handle the fault, unlock * it and return the fault to userspace. */ if (ret && (rt_mutex_owner(&q.pi_state->pi_mutex) == current)) { pi_state = q.pi_state; get_pi_state(pi_state); } /* Unqueue and drop the lock */ unqueue_me_pi(&q); if (pi_state) { rt_mutex_futex_unlock(&pi_state->pi_mutex); put_pi_state(pi_state); } goto out_put_key; out_unlock_put_key: Loading Loading @@ -3230,7 +3233,6 @@ static int futex_wait_requeue_pi(u32 __user *uaddr, unsigned int flags, u32 __user *uaddr2) { struct hrtimer_sleeper timeout, *to = NULL; struct futex_pi_state *pi_state = NULL; struct rt_mutex_waiter rt_waiter; struct futex_hash_bucket *hb; union futex_key key2 = FUTEX_KEY_INIT; Loading Loading @@ -3315,10 +3317,6 @@ static int futex_wait_requeue_pi(u32 __user *uaddr, unsigned int flags, if (q.pi_state && (q.pi_state->owner != current)) { spin_lock(q.lock_ptr); ret = fixup_pi_state_owner(uaddr2, &q, current); if (ret < 0 && rt_mutex_owner(&q.pi_state->pi_mutex) == current) { pi_state = q.pi_state; get_pi_state(pi_state); } /* * Drop the reference to the pi state which * the requeue_pi() code acquired for us. Loading Loading @@ -3360,25 +3358,10 @@ static int futex_wait_requeue_pi(u32 __user *uaddr, unsigned int flags, if (res) ret = (res < 0) ? res : 0; /* * If fixup_pi_state_owner() faulted and was unable to handle * the fault, unlock the rt_mutex and return the fault to * userspace. */ if (ret && rt_mutex_owner(&q.pi_state->pi_mutex) == current) { pi_state = q.pi_state; get_pi_state(pi_state); } /* Unqueue and drop the lock. */ unqueue_me_pi(&q); } if (pi_state) { rt_mutex_futex_unlock(&pi_state->pi_mutex); put_pi_state(pi_state); } if (ret == -EINTR) { /* * We've already been requeued, but cannot restart by calling Loading