diff options
-rw-r--r-- | kernel/futex.c | 24 |
1 files changed, 20 insertions, 4 deletions
diff --git a/kernel/futex.c b/kernel/futex.c index d077201b393d..f0dea283e77e 100644 --- a/kernel/futex.c +++ b/kernel/futex.c | |||
@@ -115,6 +115,9 @@ struct futex_q { | |||
115 | /* rt_waiter storage for requeue_pi: */ | 115 | /* rt_waiter storage for requeue_pi: */ |
116 | struct rt_mutex_waiter *rt_waiter; | 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 | /* Bitset for the optional bitmasked wakeup */ | 121 | /* Bitset for the optional bitmasked wakeup */ |
119 | u32 bitset; | 122 | u32 bitset; |
120 | }; | 123 | }; |
@@ -1080,6 +1083,10 @@ static int futex_proxy_trylock_atomic(u32 __user *pifutex, | |||
1080 | if (!top_waiter) | 1083 | if (!top_waiter) |
1081 | return 0; | 1084 | return 0; |
1082 | 1085 | ||
1086 | /* Ensure we requeue to the expected futex. */ | ||
1087 | if (!match_futex(top_waiter->requeue_pi_key, key2)) | ||
1088 | return -EINVAL; | ||
1089 | |||
1083 | /* | 1090 | /* |
1084 | * Try to take the lock for top_waiter. Set the FUTEX_WAITERS bit in | 1091 | * Try to take the lock for top_waiter. Set the FUTEX_WAITERS bit in |
1085 | * the contended case or if set_waiters is 1. The pi_state is returned | 1092 | * the contended case or if set_waiters is 1. The pi_state is returned |
@@ -1260,6 +1267,12 @@ retry_private: | |||
1260 | continue; | 1267 | continue; |
1261 | } | 1268 | } |
1262 | 1269 | ||
1270 | /* Ensure we requeue to the expected futex for requeue_pi. */ | ||
1271 | if (requeue_pi && !match_futex(this->requeue_pi_key, &key2)) { | ||
1272 | ret = -EINVAL; | ||
1273 | break; | ||
1274 | } | ||
1275 | |||
1263 | /* | 1276 | /* |
1264 | * Requeue nr_requeue waiters and possibly one more in the case | 1277 | * Requeue nr_requeue waiters and possibly one more in the case |
1265 | * of requeue_pi if we couldn't acquire the lock atomically. | 1278 | * of requeue_pi if we couldn't acquire the lock atomically. |
@@ -1735,6 +1748,7 @@ static int futex_wait(u32 __user *uaddr, int fshared, | |||
1735 | q.pi_state = NULL; | 1748 | q.pi_state = NULL; |
1736 | q.bitset = bitset; | 1749 | q.bitset = bitset; |
1737 | q.rt_waiter = NULL; | 1750 | q.rt_waiter = NULL; |
1751 | q.requeue_pi_key = NULL; | ||
1738 | 1752 | ||
1739 | if (abs_time) { | 1753 | if (abs_time) { |
1740 | to = &timeout; | 1754 | to = &timeout; |
@@ -1842,6 +1856,7 @@ static int futex_lock_pi(u32 __user *uaddr, int fshared, | |||
1842 | 1856 | ||
1843 | q.pi_state = NULL; | 1857 | q.pi_state = NULL; |
1844 | q.rt_waiter = NULL; | 1858 | q.rt_waiter = NULL; |
1859 | q.requeue_pi_key = NULL; | ||
1845 | retry: | 1860 | retry: |
1846 | q.key = FUTEX_KEY_INIT; | 1861 | q.key = FUTEX_KEY_INIT; |
1847 | ret = get_futex_key(uaddr, fshared, &q.key, VERIFY_WRITE); | 1862 | ret = get_futex_key(uaddr, fshared, &q.key, VERIFY_WRITE); |
@@ -2153,15 +2168,16 @@ static int futex_wait_requeue_pi(u32 __user *uaddr, int fshared, | |||
2153 | debug_rt_mutex_init_waiter(&rt_waiter); | 2168 | debug_rt_mutex_init_waiter(&rt_waiter); |
2154 | rt_waiter.task = NULL; | 2169 | rt_waiter.task = NULL; |
2155 | 2170 | ||
2156 | q.pi_state = NULL; | ||
2157 | q.bitset = bitset; | ||
2158 | q.rt_waiter = &rt_waiter; | ||
2159 | |||
2160 | key2 = FUTEX_KEY_INIT; | 2171 | key2 = FUTEX_KEY_INIT; |
2161 | ret = get_futex_key(uaddr2, fshared, &key2, VERIFY_WRITE); | 2172 | ret = get_futex_key(uaddr2, fshared, &key2, VERIFY_WRITE); |
2162 | if (unlikely(ret != 0)) | 2173 | if (unlikely(ret != 0)) |
2163 | goto out; | 2174 | goto out; |
2164 | 2175 | ||
2176 | q.pi_state = NULL; | ||
2177 | q.bitset = bitset; | ||
2178 | q.rt_waiter = &rt_waiter; | ||
2179 | q.requeue_pi_key = &key2; | ||
2180 | |||
2165 | /* Prepare to wait on uaddr. */ | 2181 | /* Prepare to wait on uaddr. */ |
2166 | ret = futex_wait_setup(uaddr, val, fshared, &q, &hb); | 2182 | ret = futex_wait_setup(uaddr, val, fshared, &q, &hb); |
2167 | if (ret) | 2183 | if (ret) |