Commit b0db954c authored by Linus Torvalds's avatar Linus Torvalds

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

Pull futex fix from Thomas Gleixner:
 "Single fix for a long standing futex race when taking over a futex
  whose owner died.  You can end up with two owners, which violates
  quite some rules."

* 'core-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  futex: Handle futex_pi OWNER_DIED take over correctly
parents 77b67063 59fa6245
...@@ -716,7 +716,7 @@ static int futex_lock_pi_atomic(u32 __user *uaddr, struct futex_hash_bucket *hb, ...@@ -716,7 +716,7 @@ static int futex_lock_pi_atomic(u32 __user *uaddr, struct futex_hash_bucket *hb,
struct futex_pi_state **ps, struct futex_pi_state **ps,
struct task_struct *task, int set_waiters) struct task_struct *task, int set_waiters)
{ {
int lock_taken, ret, ownerdied = 0; int lock_taken, ret, force_take = 0;
u32 uval, newval, curval, vpid = task_pid_vnr(task); u32 uval, newval, curval, vpid = task_pid_vnr(task);
retry: retry:
...@@ -755,17 +755,15 @@ static int futex_lock_pi_atomic(u32 __user *uaddr, struct futex_hash_bucket *hb, ...@@ -755,17 +755,15 @@ static int futex_lock_pi_atomic(u32 __user *uaddr, struct futex_hash_bucket *hb,
newval = curval | FUTEX_WAITERS; newval = curval | FUTEX_WAITERS;
/* /*
* There are two cases, where a futex might have no owner (the * Should we force take the futex? See below.
* owner TID is 0): OWNER_DIED. We take over the futex in this */
* case. We also do an unconditional take over, when the owner if (unlikely(force_take)) {
* of the futex died. /*
* * Keep the OWNER_DIED and the WAITERS bit and set the
* This is safe as we are protected by the hash bucket lock ! * new TID value.
*/ */
if (unlikely(ownerdied || !(curval & FUTEX_TID_MASK))) {
/* Keep the OWNER_DIED bit */
newval = (curval & ~FUTEX_TID_MASK) | vpid; newval = (curval & ~FUTEX_TID_MASK) | vpid;
ownerdied = 0; force_take = 0;
lock_taken = 1; lock_taken = 1;
} }
...@@ -775,7 +773,7 @@ static int futex_lock_pi_atomic(u32 __user *uaddr, struct futex_hash_bucket *hb, ...@@ -775,7 +773,7 @@ static int futex_lock_pi_atomic(u32 __user *uaddr, struct futex_hash_bucket *hb,
goto retry; goto retry;
/* /*
* We took the lock due to owner died take over. * We took the lock due to forced take over.
*/ */
if (unlikely(lock_taken)) if (unlikely(lock_taken))
return 1; return 1;
...@@ -790,20 +788,25 @@ static int futex_lock_pi_atomic(u32 __user *uaddr, struct futex_hash_bucket *hb, ...@@ -790,20 +788,25 @@ static int futex_lock_pi_atomic(u32 __user *uaddr, struct futex_hash_bucket *hb,
switch (ret) { switch (ret) {
case -ESRCH: case -ESRCH:
/* /*
* No owner found for this futex. Check if the * We failed to find an owner for this
* OWNER_DIED bit is set to figure out whether * futex. So we have no pi_state to block
* this is a robust futex or not. * on. This can happen in two cases:
*
* 1) The owner died
* 2) A stale FUTEX_WAITERS bit
*
* Re-read the futex value.
*/ */
if (get_futex_value_locked(&curval, uaddr)) if (get_futex_value_locked(&curval, uaddr))
return -EFAULT; return -EFAULT;
/* /*
* We simply start over in case of a robust * If the owner died or we have a stale
* futex. The code above will take the futex * WAITERS bit the owner TID in the user space
* and return happy. * futex is 0.
*/ */
if (curval & FUTEX_OWNER_DIED) { if (!(curval & FUTEX_TID_MASK)) {
ownerdied = 1; force_take = 1;
goto retry; goto retry;
} }
default: default:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment