Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b0db954c authored by Linus Torvalds's avatar Linus Torvalds
Browse files

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
Loading
Loading
Loading
Loading
+22 −19
Original line number Original line Diff line number Diff line
@@ -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,
	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,
		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,
		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: