[tip: locking/urgent] futex/requeue: Prevent NULL pointer dereference in remove_waiter() on self-deadlock

tip-bot2 for Ji'an Zhou posted 1 patch 5 days, 7 hours ago
kernel/futex/requeue.c | 6 ++++++
1 file changed, 6 insertions(+)
[tip: locking/urgent] futex/requeue: Prevent NULL pointer dereference in remove_waiter() on self-deadlock
Posted by tip-bot2 for Ji'an Zhou 5 days, 7 hours ago
The following commit has been merged into the locking/urgent branch of tip:

Commit-ID:     74e144274af39935b0f410c0ee4d2b91c3730414
Gitweb:        https://git.kernel.org/tip/74e144274af39935b0f410c0ee4d2b91c3730414
Author:        Ji'an Zhou <eilaimemedsnaimel@gmail.com>
AuthorDate:    Tue, 02 Jun 2026 09:12:04 
Committer:     Thomas Gleixner <tglx@kernel.org>
CommitterDate: Tue, 02 Jun 2026 22:27:04 +02:00

futex/requeue: Prevent NULL pointer dereference in remove_waiter() on self-deadlock

When FUTEX_CMP_REQUEUE_PI requeues a non-top waiter that already owns the
target PI futex, task_blocks_on_rt_mutex() returns -EDEADLK before setting
waiter->task.

The subsequent remove_waiter() in rt_mutex_start_proxy_lock() dereferences
the NULL waiter->task, causing a kernel crash.

Add a self-deadlock check for non-top waiters before calling
rt_mutex_start_proxy_lock(), analogous to the top-waiter check in
futex_lock_pi_atomic().

Fixes: 3bfdc63936dd4773109b7b8c280c0f3b5ae7d349 ("rtmutex: Use waiter::task instead of current in remove_waiter()")
Signed-off-by: Ji'an Zhou <eilaimemedsnaimel@gmail.com>
Signed-off-by: Thomas Gleixner <tglx@kernel.org>
Cc: stable@vger.kernel.org
---
 kernel/futex/requeue.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/kernel/futex/requeue.c b/kernel/futex/requeue.c
index b597cb3..1d99a84 100644
--- a/kernel/futex/requeue.c
+++ b/kernel/futex/requeue.c
@@ -643,6 +643,12 @@ retry_private:
 				continue;
 			}
 
+			/* Self-deadlock: non-top waiter already owns the PI futex. */
+			if (rt_mutex_owner(&pi_state->pi_mutex) == this->task) {
+				ret = -EDEADLK;
+				break;
+			}
+
 			ret = rt_mutex_start_proxy_lock(&pi_state->pi_mutex,
 							this->rt_waiter,
 							this->task);