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.2_rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull locking fixes from Borislav Petkov:

- Prevent the leaking of a debug timer in futex_waitv()

- A preempt-RT mutex locking fix, adding the proper acquire semantics

* tag 'locking_urgent_for_v6.2_rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
futex: Fix futex_waitv() hrtimer debug object leak on kcalloc error
rtmutex: Add acquire semantics for rtmutex lock acquisition slow path

+56 -16
+7 -4
kernel/futex/syscalls.c
··· 286 286 } 287 287 288 288 futexv = kcalloc(nr_futexes, sizeof(*futexv), GFP_KERNEL); 289 - if (!futexv) 290 - return -ENOMEM; 289 + if (!futexv) { 290 + ret = -ENOMEM; 291 + goto destroy_timer; 292 + } 291 293 292 294 ret = futex_parse_waitv(futexv, waiters, nr_futexes); 293 295 if (!ret) 294 296 ret = futex_wait_multiple(futexv, nr_futexes, timeout ? &to : NULL); 295 297 298 + kfree(futexv); 299 + 300 + destroy_timer: 296 301 if (timeout) { 297 302 hrtimer_cancel(&to.timer); 298 303 destroy_hrtimer_on_stack(&to.timer); 299 304 } 300 - 301 - kfree(futexv); 302 305 return ret; 303 306 } 304 307
+46 -9
kernel/locking/rtmutex.c
··· 89 89 * set this bit before looking at the lock. 90 90 */ 91 91 92 - static __always_inline void 93 - rt_mutex_set_owner(struct rt_mutex_base *lock, struct task_struct *owner) 92 + static __always_inline struct task_struct * 93 + rt_mutex_owner_encode(struct rt_mutex_base *lock, struct task_struct *owner) 94 94 { 95 95 unsigned long val = (unsigned long)owner; 96 96 97 97 if (rt_mutex_has_waiters(lock)) 98 98 val |= RT_MUTEX_HAS_WAITERS; 99 99 100 - WRITE_ONCE(lock->owner, (struct task_struct *)val); 100 + return (struct task_struct *)val; 101 + } 102 + 103 + static __always_inline void 104 + rt_mutex_set_owner(struct rt_mutex_base *lock, struct task_struct *owner) 105 + { 106 + /* 107 + * lock->wait_lock is held but explicit acquire semantics are needed 108 + * for a new lock owner so WRITE_ONCE is insufficient. 109 + */ 110 + xchg_acquire(&lock->owner, rt_mutex_owner_encode(lock, owner)); 111 + } 112 + 113 + static __always_inline void rt_mutex_clear_owner(struct rt_mutex_base *lock) 114 + { 115 + /* lock->wait_lock is held so the unlock provides release semantics. */ 116 + WRITE_ONCE(lock->owner, rt_mutex_owner_encode(lock, NULL)); 101 117 } 102 118 103 119 static __always_inline void clear_rt_mutex_waiters(struct rt_mutex_base *lock) ··· 122 106 ((unsigned long)lock->owner & ~RT_MUTEX_HAS_WAITERS); 123 107 } 124 108 125 - static __always_inline void fixup_rt_mutex_waiters(struct rt_mutex_base *lock) 109 + static __always_inline void 110 + fixup_rt_mutex_waiters(struct rt_mutex_base *lock, bool acquire_lock) 126 111 { 127 112 unsigned long owner, *p = (unsigned long *) &lock->owner; 128 113 ··· 189 172 * still set. 190 173 */ 191 174 owner = READ_ONCE(*p); 192 - if (owner & RT_MUTEX_HAS_WAITERS) 193 - WRITE_ONCE(*p, owner & ~RT_MUTEX_HAS_WAITERS); 175 + if (owner & RT_MUTEX_HAS_WAITERS) { 176 + /* 177 + * See rt_mutex_set_owner() and rt_mutex_clear_owner() on 178 + * why xchg_acquire() is used for updating owner for 179 + * locking and WRITE_ONCE() for unlocking. 180 + * 181 + * WRITE_ONCE() would work for the acquire case too, but 182 + * in case that the lock acquisition failed it might 183 + * force other lockers into the slow path unnecessarily. 184 + */ 185 + if (acquire_lock) 186 + xchg_acquire(p, owner & ~RT_MUTEX_HAS_WAITERS); 187 + else 188 + WRITE_ONCE(*p, owner & ~RT_MUTEX_HAS_WAITERS); 189 + } 194 190 } 195 191 196 192 /* ··· 238 208 owner = *p; 239 209 } while (cmpxchg_relaxed(p, owner, 240 210 owner | RT_MUTEX_HAS_WAITERS) != owner); 211 + 212 + /* 213 + * The cmpxchg loop above is relaxed to avoid back-to-back ACQUIRE 214 + * operations in the event of contention. Ensure the successful 215 + * cmpxchg is visible. 216 + */ 217 + smp_mb__after_atomic(); 241 218 } 242 219 243 220 /* ··· 1280 1243 * try_to_take_rt_mutex() sets the lock waiters bit 1281 1244 * unconditionally. Clean this up. 1282 1245 */ 1283 - fixup_rt_mutex_waiters(lock); 1246 + fixup_rt_mutex_waiters(lock, true); 1284 1247 1285 1248 return ret; 1286 1249 } ··· 1641 1604 * try_to_take_rt_mutex() sets the waiter bit 1642 1605 * unconditionally. We might have to fix that up. 1643 1606 */ 1644 - fixup_rt_mutex_waiters(lock); 1607 + fixup_rt_mutex_waiters(lock, true); 1645 1608 1646 1609 trace_contention_end(lock, ret); 1647 1610 ··· 1756 1719 * try_to_take_rt_mutex() sets the waiter bit unconditionally. 1757 1720 * We might have to fix that up: 1758 1721 */ 1759 - fixup_rt_mutex_waiters(lock); 1722 + fixup_rt_mutex_waiters(lock, true); 1760 1723 debug_rt_mutex_free_waiter(&waiter); 1761 1724 1762 1725 trace_contention_end(lock, 0);
+3 -3
kernel/locking/rtmutex_api.c
··· 267 267 void __sched rt_mutex_proxy_unlock(struct rt_mutex_base *lock) 268 268 { 269 269 debug_rt_mutex_proxy_unlock(lock); 270 - rt_mutex_set_owner(lock, NULL); 270 + rt_mutex_clear_owner(lock); 271 271 } 272 272 273 273 /** ··· 382 382 * try_to_take_rt_mutex() sets the waiter bit unconditionally. We might 383 383 * have to fix that up. 384 384 */ 385 - fixup_rt_mutex_waiters(lock); 385 + fixup_rt_mutex_waiters(lock, true); 386 386 raw_spin_unlock_irq(&lock->wait_lock); 387 387 388 388 return ret; ··· 438 438 * try_to_take_rt_mutex() sets the waiter bit unconditionally. We might 439 439 * have to fix that up. 440 440 */ 441 - fixup_rt_mutex_waiters(lock); 441 + fixup_rt_mutex_waiters(lock, false); 442 442 443 443 raw_spin_unlock_irq(&lock->wait_lock); 444 444