Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'locking_urgent_for_v6.8_rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull locking fix from Borislav Petkov:

- Prevent an inconsistent futex operation leading to stale state
exposure

* tag 'locking_urgent_for_v6.8_rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
futex: Prevent the reuse of stale pi_state

+20 -6
+12 -3
kernel/futex/core.c
··· 627 627 } 628 628 629 629 /* 630 - * PI futexes can not be requeued and must remove themselves from the 631 - * hash bucket. The hash bucket lock (i.e. lock_ptr) is held. 630 + * PI futexes can not be requeued and must remove themselves from the hash 631 + * bucket. The hash bucket lock (i.e. lock_ptr) is held. 632 632 */ 633 633 void futex_unqueue_pi(struct futex_q *q) 634 634 { 635 - __futex_unqueue(q); 635 + /* 636 + * If the lock was not acquired (due to timeout or signal) then the 637 + * rt_waiter is removed before futex_q is. If this is observed by 638 + * an unlocker after dropping the rtmutex wait lock and before 639 + * acquiring the hash bucket lock, then the unlocker dequeues the 640 + * futex_q from the hash bucket list to guarantee consistent state 641 + * vs. userspace. Therefore the dequeue here must be conditional. 642 + */ 643 + if (!plist_node_empty(&q->list)) 644 + __futex_unqueue(q); 636 645 637 646 BUG_ON(!q->pi_state); 638 647 put_pi_state(q->pi_state);
+8 -3
kernel/futex/pi.c
··· 1135 1135 1136 1136 hb = futex_hash(&key); 1137 1137 spin_lock(&hb->lock); 1138 + retry_hb: 1138 1139 1139 1140 /* 1140 1141 * Check waiters first. We do not trust user space values at ··· 1178 1177 /* 1179 1178 * Futex vs rt_mutex waiter state -- if there are no rt_mutex 1180 1179 * waiters even though futex thinks there are, then the waiter 1181 - * is leaving and the uncontended path is safe to take. 1180 + * is leaving. The entry needs to be removed from the list so a 1181 + * new futex_lock_pi() is not using this stale PI-state while 1182 + * the futex is available in user space again. 1183 + * There can be more than one task on its way out so it needs 1184 + * to retry. 1182 1185 */ 1183 1186 rt_waiter = rt_mutex_top_waiter(&pi_state->pi_mutex); 1184 1187 if (!rt_waiter) { 1188 + __futex_unqueue(top_waiter); 1185 1189 raw_spin_unlock_irq(&pi_state->pi_mutex.wait_lock); 1186 - goto do_uncontended; 1190 + goto retry_hb; 1187 1191 } 1188 1192 1189 1193 get_pi_state(pi_state); ··· 1223 1217 return ret; 1224 1218 } 1225 1219 1226 - do_uncontended: 1227 1220 /* 1228 1221 * We have no kernel internal state, i.e. no waiters in the 1229 1222 * kernel. Waiters which are about to queue themselves are stuck