Commit 6f7b0a2a5c0fb03be7c25bd1745baa50582348ef

Authored by Darren Hart
Committed by Thomas Gleixner
1 parent f27071cb7f

futex: Forbid uaddr == uaddr2 in futex_wait_requeue_pi()

If uaddr == uaddr2, then we have broken the rule of only requeueing
from a non-pi futex to a pi futex with this call. If we attempt this,
as the trinity test suite manages to do, we miss early wakeups as
q.key is equal to key2 (because they are the same uaddr). We will then
attempt to dereference the pi_mutex (which would exist had the futex_q
been properly requeued to a pi futex) and trigger a NULL pointer
dereference.

Signed-off-by: Darren Hart <dvhart@linux.intel.com>
Cc: Dave Jones <davej@redhat.com>
Cc: stable@vger.kernel.org
Link: http://lkml.kernel.org/r/ad82bfe7f7d130247fbe2b5b4275654807774227.1342809673.git.dvhart@linux.intel.com
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

Showing 1 changed file with 8 additions and 5 deletions Side-by-side Diff

... ... @@ -2231,11 +2231,11 @@
2231 2231 * @uaddr2: the pi futex we will take prior to returning to user-space
2232 2232 *
2233 2233 * The caller will wait on uaddr and will be requeued by futex_requeue() to
2234   - * uaddr2 which must be PI aware. Normal wakeup will wake on uaddr2 and
2235   - * complete the acquisition of the rt_mutex prior to returning to userspace.
2236   - * This ensures the rt_mutex maintains an owner when it has waiters; without
2237   - * one, the pi logic wouldn't know which task to boost/deboost, if there was a
2238   - * need to.
  2234 + * uaddr2 which must be PI aware and unique from uaddr. Normal wakeup will wake
  2235 + * on uaddr2 and complete the acquisition of the rt_mutex prior to returning to
  2236 + * userspace. This ensures the rt_mutex maintains an owner when it has waiters;
  2237 + * without one, the pi logic would not know which task to boost/deboost, if
  2238 + * there was a need to.
2239 2239 *
2240 2240 * We call schedule in futex_wait_queue_me() when we enqueue and return there
2241 2241 * via the following:
... ... @@ -2271,6 +2271,9 @@
2271 2271 union futex_key key2 = FUTEX_KEY_INIT;
2272 2272 struct futex_q q = futex_q_init;
2273 2273 int res, ret;
  2274 +
  2275 + if (uaddr == uaddr2)
  2276 + return -EINVAL;
2274 2277  
2275 2278 if (!bitset)
2276 2279 return -EINVAL;