Commit 7193bea53f9d9730bbc859777c2f86c76349914d

Authored by Linus Torvalds

Merge branch 'core-futexes-for-linus' of git://git.kernel.org/pub/scm/linux/kern…

…el/git/tip/linux-2.6-tip

* 'core-futexes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip:
  futex: Detect mismatched requeue targets
  futex: Correct futex_wait_requeue_pi() commentary

Showing 1 changed file Side-by-side Diff

... ... @@ -115,6 +115,9 @@
115 115 /* rt_waiter storage for requeue_pi: */
116 116 struct rt_mutex_waiter *rt_waiter;
117 117  
  118 + /* The expected requeue pi target futex key: */
  119 + union futex_key *requeue_pi_key;
  120 +
118 121 /* Bitset for the optional bitmasked wakeup */
119 122 u32 bitset;
120 123 };
... ... @@ -1089,6 +1092,10 @@
1089 1092 if (!top_waiter)
1090 1093 return 0;
1091 1094  
  1095 + /* Ensure we requeue to the expected futex. */
  1096 + if (!match_futex(top_waiter->requeue_pi_key, key2))
  1097 + return -EINVAL;
  1098 +
1092 1099 /*
1093 1100 * Try to take the lock for top_waiter. Set the FUTEX_WAITERS bit in
1094 1101 * the contended case or if set_waiters is 1. The pi_state is returned
... ... @@ -1276,6 +1283,12 @@
1276 1283 continue;
1277 1284 }
1278 1285  
  1286 + /* Ensure we requeue to the expected futex for requeue_pi. */
  1287 + if (requeue_pi && !match_futex(this->requeue_pi_key, &key2)) {
  1288 + ret = -EINVAL;
  1289 + break;
  1290 + }
  1291 +
1279 1292 /*
1280 1293 * Requeue nr_requeue waiters and possibly one more in the case
1281 1294 * of requeue_pi if we couldn't acquire the lock atomically.
... ... @@ -1751,6 +1764,7 @@
1751 1764 q.pi_state = NULL;
1752 1765 q.bitset = bitset;
1753 1766 q.rt_waiter = NULL;
  1767 + q.requeue_pi_key = NULL;
1754 1768  
1755 1769 if (abs_time) {
1756 1770 to = &timeout;
... ... @@ -1858,6 +1872,7 @@
1858 1872  
1859 1873 q.pi_state = NULL;
1860 1874 q.rt_waiter = NULL;
  1875 + q.requeue_pi_key = NULL;
1861 1876 retry:
1862 1877 q.key = FUTEX_KEY_INIT;
1863 1878 ret = get_futex_key(uaddr, fshared, &q.key, VERIFY_WRITE);
1864 1879  
... ... @@ -2118,11 +2133,11 @@
2118 2133 * We call schedule in futex_wait_queue_me() when we enqueue and return there
2119 2134 * via the following:
2120 2135 * 1) wakeup on uaddr2 after an atomic lock acquisition by futex_requeue()
2121   - * 2) wakeup on uaddr2 after a requeue and subsequent unlock
2122   - * 3) signal (before or after requeue)
2123   - * 4) timeout (before or after requeue)
  2136 + * 2) wakeup on uaddr2 after a requeue
  2137 + * 3) signal
  2138 + * 4) timeout
2124 2139 *
2125   - * If 3, we setup a restart_block with futex_wait_requeue_pi() as the function.
  2140 + * If 3, cleanup and return -ERESTARTNOINTR.
2126 2141 *
2127 2142 * If 2, we may then block on trying to take the rt_mutex and return via:
2128 2143 * 5) successful lock
... ... @@ -2130,7 +2145,7 @@
2130 2145 * 7) timeout
2131 2146 * 8) other lock acquisition failure
2132 2147 *
2133   - * If 6, we setup a restart_block with futex_lock_pi() as the function.
  2148 + * If 6, return -EWOULDBLOCK (restarting the syscall would do the same).
2134 2149 *
2135 2150 * If 4 or 7, we cleanup and return with -ETIMEDOUT.
2136 2151 *
2137 2152  
... ... @@ -2169,15 +2184,16 @@
2169 2184 debug_rt_mutex_init_waiter(&rt_waiter);
2170 2185 rt_waiter.task = NULL;
2171 2186  
2172   - q.pi_state = NULL;
2173   - q.bitset = bitset;
2174   - q.rt_waiter = &rt_waiter;
2175   -
2176 2187 key2 = FUTEX_KEY_INIT;
2177 2188 ret = get_futex_key(uaddr2, fshared, &key2, VERIFY_WRITE);
2178 2189 if (unlikely(ret != 0))
2179 2190 goto out;
2180 2191  
  2192 + q.pi_state = NULL;
  2193 + q.bitset = bitset;
  2194 + q.rt_waiter = &rt_waiter;
  2195 + q.requeue_pi_key = &key2;
  2196 +
2181 2197 /* Prepare to wait on uaddr. */
2182 2198 ret = futex_wait_setup(uaddr, val, fshared, &q, &hb);
2183 2199 if (ret)
... ... @@ -2248,14 +2264,11 @@
2248 2264 rt_mutex_unlock(pi_mutex);
2249 2265 } else if (ret == -EINTR) {
2250 2266 /*
2251   - * We've already been requeued, but we have no way to
2252   - * restart by calling futex_lock_pi() directly. We
2253   - * could restart the syscall, but that will look at
2254   - * the user space value and return right away. So we
2255   - * drop back with EWOULDBLOCK to tell user space that
2256   - * "val" has been changed. That's the same what the
2257   - * restart of the syscall would do in
2258   - * futex_wait_setup().
  2267 + * We've already been requeued, but cannot restart by calling
  2268 + * futex_lock_pi() directly. We could restart this syscall, but
  2269 + * it would detect that the user space "val" changed and return
  2270 + * -EWOULDBLOCK. Save the overhead of the restart and return
  2271 + * -EWOULDBLOCK directly.
2259 2272 */
2260 2273 ret = -EWOULDBLOCK;
2261 2274 }