linux-stable/kernel/locking
Peter Zijlstra 7f1715d827 locking/rtmutex: Fix task->pi_waiters integrity
[ Upstream commit f7853c3424 ]

Henry reported that rt_mutex_adjust_prio_check() has an ordering
problem and puts the lie to the comment in [7]. Sharing the sort key
between lock->waiters and owner->pi_waiters *does* create problems,
since unlike what the comment claims, holding [L] is insufficient.

Notably, consider:

	A
      /   \
     M1   M2
     |     |
     B     C

That is, task A owns both M1 and M2, B and C block on them. In this
case a concurrent chain walk (B & C) will modify their resp. sort keys
in [7] while holding M1->wait_lock and M2->wait_lock. So holding [L]
is meaningless, they're different Ls.

This then gives rise to a race condition between [7] and [11], where
the requeue of pi_waiters will observe an inconsistent tree order.

	B				C

  (holds M1->wait_lock,		(holds M2->wait_lock,
   holds B->pi_lock)		 holds A->pi_lock)

  [7]
  waiter_update_prio();
  ...
  [8]
  raw_spin_unlock(B->pi_lock);
  ...
  [10]
  raw_spin_lock(A->pi_lock);

				[11]
				rt_mutex_enqueue_pi();
				// observes inconsistent A->pi_waiters
				// tree order

Fixing this means either extending the range of the owner lock from
[10-13] to [6-13], with the immediate problem that this means [6-8]
hold both blocked and owner locks, or duplicating the sort key.

Since the locking in chain walk is horrible enough without having to
consider pi_lock nesting rules, duplicate the sort key instead.

By giving each tree their own sort key, the above race becomes
harmless, if C sees B at the old location, then B will correct things
(if they need correcting) when it walks up the chain and reaches A.

Fixes: fb00aca474 ("rtmutex: Turn the plist into an rb-tree")
Reported-by: Henry Wu <triangletrap12@gmail.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Acked-by: Thomas Gleixner <tglx@linutronix.de>
Tested-by: Henry Wu <triangletrap12@gmail.com>
Link: https://lkml.kernel.org/r/20230707161052.GF2883469%40hirez.programming.kicks-ass.net
Signed-off-by: Sasha Levin <sashal@kernel.org>
2023-08-03 10:24:14 +02:00
..
irqflag-debug.c
lock_events.c
lock_events.h
lock_events_list.h
lockdep.c cpuidle: lib/bug: Disable rcu_is_watching() during WARN/BUG 2023-03-10 09:33:47 +01:00
lockdep_internals.h
lockdep_proc.c
lockdep_states.h
locktorture.c
Makefile
mcs_spinlock.h
mutex-debug.c
mutex.c
mutex.h
osq_lock.c
percpu-rwsem.c
qrwlock.c
qspinlock.c
qspinlock_paravirt.h
qspinlock_stat.h
rtmutex.c locking/rtmutex: Fix task->pi_waiters integrity 2023-08-03 10:24:14 +02:00
rtmutex_api.c locking/rtmutex: Fix task->pi_waiters integrity 2023-08-03 10:24:14 +02:00
rtmutex_common.h locking/rtmutex: Fix task->pi_waiters integrity 2023-08-03 10:24:14 +02:00
rwbase_rt.c
rwsem.c locking/rwsem: Add __always_inline annotation to __down_read_common() and inlined callers 2023-05-17 11:53:57 +02:00
semaphore.c
spinlock.c
spinlock_debug.c
spinlock_rt.c
test-ww_mutex.c
ww_mutex.h locking/rtmutex: Fix task->pi_waiters integrity 2023-08-03 10:24:14 +02:00
ww_rt_mutex.c