All of lore.kernel.org
 help / color / mirror / Atom feed
* FAILED: patch "[PATCH] futex/requeue: Prevent NULL pointer dereference in" failed to apply to 5.15-stable tree
@ 2026-07-21 15:13 gregkh
  2026-07-22 16:14 ` [patch 5.15.y 0/2] rtmutex/futex: Backport of rejecting fixes Thomas Gleixner
  0 siblings, 1 reply; 4+ messages in thread
From: gregkh @ 2026-07-21 15:13 UTC (permalink / raw)
  To: eilaimemedsnaimel, tglx; +Cc: stable


The patch below does not apply to the 5.15-stable tree.
If someone wants it applied there, or to any other stable or longterm
tree, then please email the backport, including the original git commit
id to <stable@vger.kernel.org>.

To reproduce the conflict and resubmit, you may use the following commands:

git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-5.15.y
git checkout FETCH_HEAD
git cherry-pick -x 74e144274af39935b0f410c0ee4d2b91c3730414
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<stable@vger.kernel.org>' --in-reply-to '2026072141-ravage-display-0696@gregkh' --subject-prefix 'PATCH 5.15.y' 'HEAD^..'

Possible dependencies:



thanks,

greg k-h

------------------ original commit in Linus's tree ------------------

From 74e144274af39935b0f410c0ee4d2b91c3730414 Mon Sep 17 00:00:00 2001
From: Ji'an Zhou <eilaimemedsnaimel@gmail.com>
Date: Tue, 2 Jun 2026 09:12:04 +0000
Subject: [PATCH] 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

diff --git a/kernel/futex/requeue.c b/kernel/futex/requeue.c
index b597cb3d17fc..1d99a84dc9ad 100644
--- a/kernel/futex/requeue.c
+++ b/kernel/futex/requeue.c
@@ -643,6 +643,12 @@ int futex_requeue(u32 __user *uaddr1, unsigned int flags1,
 				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);


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [patch 5.15.y 0/2] rtmutex/futex: Backport of rejecting fixes
  2026-07-21 15:13 FAILED: patch "[PATCH] futex/requeue: Prevent NULL pointer dereference in" failed to apply to 5.15-stable tree gregkh
@ 2026-07-22 16:14 ` Thomas Gleixner
  2026-07-22 16:14   ` [patch 5.15.y 1/2] rtmutex: Use waiter::task instead of current in remove_waiter() Thomas Gleixner
  2026-07-22 16:15   ` [patch 5.15.y 2/2] locking/rtmutex: Skip remove_waiter() when waiter is not enqueued Thomas Gleixner
  0 siblings, 2 replies; 4+ messages in thread
From: Thomas Gleixner @ 2026-07-22 16:14 UTC (permalink / raw)
  To: stable; +Cc: tglx

As promised the backports of:

   3bfdc63936dd ("rtmutex: Use waiter::task instead of current in remove_waiter()")
   40a25d59e85b ("locking/rtmutex: Skip remove_waiter() when waiter is not enqueued")

for 5.15.y.

Thanks,

	tglx



^ permalink raw reply	[flat|nested] 4+ messages in thread

* [patch 5.15.y 1/2] rtmutex: Use waiter::task instead of current in remove_waiter()
  2026-07-22 16:14 ` [patch 5.15.y 0/2] rtmutex/futex: Backport of rejecting fixes Thomas Gleixner
@ 2026-07-22 16:14   ` Thomas Gleixner
  2026-07-22 16:15   ` [patch 5.15.y 2/2] locking/rtmutex: Skip remove_waiter() when waiter is not enqueued Thomas Gleixner
  1 sibling, 0 replies; 4+ messages in thread
From: Thomas Gleixner @ 2026-07-22 16:14 UTC (permalink / raw)
  To: stable; +Cc: tglx, Yuan Tan, Yifan Wu, Juefei Pu, Xin Liu, Keenan Dong

From: Keenan Dong <keenanat2000@gmail.com>

commit 3bfdc63936dd4773109b7b8c280c0f3b5ae7d349 upstream.

remove_waiter() is used by the slowlock paths, but it is also used for
proxy-lock rollback in rt_mutex_start_proxy_lock() when invoked from
futex_requeue().

In the latter case waiter::task is not current, but remove_waiter()
operates on current for the dequeue operation. That results in several
problems:

  1) the rbtree dequeue happens without waiter::task::pi_lock being held

  2) the waiter task's pi_blocked_on state is not cleared, which leaves a
     dangling pointer primed for UAF around.

  3) rt_mutex_adjust_prio_chain() operates on the wrong top priority waiter
     task

Use waiter::task instead of current in all related operations in
remove_waiter() to cure those problems.

[ tglx: Fixup rt_mutex_adjust_prio_chain(), add a comment and amend the
  	changelog ]

[ tglx: Backport for 5.10.y and 5.15.y. The commit has not been backported
  	yet because the Fixes tag is wrong. Fixes: points now to the real
  	culprit. ]

Fixes: a1fb985f2e2 ("futex: Handle early deadlock return correctly") ]
Reported-by: Yuan Tan <yuantan098@gmail.com>
Reported-by: Yifan Wu <yifanwucs@gmail.com>
Reported-by: Juefei Pu <tomapufckgml@gmail.com>
Reported-by: Xin Liu <bird@lzu.edu.cn>
Signed-off-by: Keenan Dong <keenanat2000@gmail.com>
Signed-off-by: Thomas Gleixner <tglx@kernel.org>
Cc: stable@vger.kernel.org
---
 kernel/locking/rtmutex.c |   11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)
---
--- a/kernel/locking/rtmutex.c
+++ b/kernel/locking/rtmutex.c
@@ -1500,20 +1500,23 @@ static bool rtmutex_spin_on_owner(struct
  *
  * Must be called with lock->wait_lock held and interrupts disabled. It must
  * have just failed to try_to_take_rt_mutex().
+ *
+ * When invoked from rt_mutex_start_proxy_lock() waiter::task != current !
  */
 static void __sched remove_waiter(struct rt_mutex_base *lock,
 				  struct rt_mutex_waiter *waiter)
 {
 	bool is_top_waiter = (waiter == rt_mutex_top_waiter(lock));
 	struct task_struct *owner = rt_mutex_owner(lock);
+	struct task_struct *waiter_task = waiter->task;
 	struct rt_mutex_base *next_lock;
 
 	lockdep_assert_held(&lock->wait_lock);
 
-	raw_spin_lock(&current->pi_lock);
+	raw_spin_lock(&waiter_task->pi_lock);
 	rt_mutex_dequeue(lock, waiter);
-	current->pi_blocked_on = NULL;
-	raw_spin_unlock(&current->pi_lock);
+	waiter_task->pi_blocked_on = NULL;
+	raw_spin_lock(&waiter_task->pi_lock);
 
 	/*
 	 * Only update priority if the waiter was the highest priority
@@ -1549,7 +1552,7 @@ static void __sched remove_waiter(struct
 	raw_spin_unlock_irq(&lock->wait_lock);
 
 	rt_mutex_adjust_prio_chain(owner, RT_MUTEX_MIN_CHAINWALK, lock,
-				   next_lock, NULL, current);
+				   next_lock, NULL, waiter_task);
 
 	raw_spin_lock_irq(&lock->wait_lock);
 }


^ permalink raw reply	[flat|nested] 4+ messages in thread

* [patch 5.15.y 2/2] locking/rtmutex: Skip remove_waiter() when waiter is not enqueued
  2026-07-22 16:14 ` [patch 5.15.y 0/2] rtmutex/futex: Backport of rejecting fixes Thomas Gleixner
  2026-07-22 16:14   ` [patch 5.15.y 1/2] rtmutex: Use waiter::task instead of current in remove_waiter() Thomas Gleixner
@ 2026-07-22 16:15   ` Thomas Gleixner
  1 sibling, 0 replies; 4+ messages in thread
From: Thomas Gleixner @ 2026-07-22 16:15 UTC (permalink / raw)
  To: stable; +Cc: tglx, syzbot+78147abe6c524f183ee9, Davidlohr Bueso

From: Davidlohr Bueso <dave@stgolabs.net>

commit 40a25d59e85b3c8709ac2424d44f65610467871e upstream.

syzbot triggered the following splat in remove_waiter() via
FUTEX_CMP_REQUEUE_PI:

  KASAN: null-ptr-deref in range [0x0000000000000a88-0x0000000000000a8f]
   class_raw_spinlock_constructor
   remove_waiter+0x159/0x1200 kernel/locking/rtmutex.c:1561
   rt_mutex_start_proxy_lock+0x103/0x120
   futex_requeue+0x10e4/0x20d0
   __x64_sys_futex+0x34f/0x4d0

task_blocks_on_rt_mutex() does not arm the waiter upon deadlock detection,
leaving waiter->task nil, where 3bfdc63936dd ("rtmutex: Use waiter::task instead
of current in remove_waiter()") made this fatal.

Furthermore, rt_mutex_start_proxy_lock() should not be calling into remove_waiter()
upon a successfully grabbing the rtmutex. 1a1fb985f2e2 ("futex: Handle early deadlock
return correctly"), moved the remove_waiter() out of __rt_mutex_start_proxy_lock()
(where 'ret' was only ever 0 or < 0) into the wrapper. Tighten this check to
account for try_to_take_rt_mutex().

Fixes: 3bfdc63936dd ("rtmutex: Use waiter::task instead of current in remove_waiter()")
Reported-by: syzbot+78147abe6c524f183ee9@syzkaller.appspotmail.com
Signed-off-by: Davidlohr Bueso <dave@stgolabs.net>
Signed-off-by: Thomas Gleixner <tglx@kernel.org>
Cc: stable@vger.kernel.org
Closes: https://lore.kernel.org/all/69f114ac.050a0220.ac8b.0003.GAE@google.com/
Link: https://patch.msgid.link/20260507112913.1019537-1-dave@stgolabs.net
---
 kernel/locking/rtmutex.c     |    3 +++
 kernel/locking/rtmutex_api.c |    2 +-
 2 files changed, 4 insertions(+), 1 deletion(-)
---
--- a/kernel/locking/rtmutex.c
+++ b/kernel/locking/rtmutex.c
@@ -1513,6 +1513,9 @@ static void __sched remove_waiter(struct
 
 	lockdep_assert_held(&lock->wait_lock);
 
+	if (!waiter_task) /* never enqueued */
+		return;
+
 	raw_spin_lock(&waiter_task->pi_lock);
 	rt_mutex_dequeue(lock, waiter);
 	waiter_task->pi_blocked_on = NULL;
--- a/kernel/locking/rtmutex_api.c
+++ b/kernel/locking/rtmutex_api.c
@@ -322,7 +322,7 @@ int __sched rt_mutex_start_proxy_lock(st
 
 	raw_spin_lock_irq(&lock->wait_lock);
 	ret = __rt_mutex_start_proxy_lock(lock, waiter, task);
-	if (unlikely(ret))
+	if (unlikely(ret < 0))
 		remove_waiter(lock, waiter);
 	raw_spin_unlock_irq(&lock->wait_lock);
 


^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2026-07-22 16:15 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-21 15:13 FAILED: patch "[PATCH] futex/requeue: Prevent NULL pointer dereference in" failed to apply to 5.15-stable tree gregkh
2026-07-22 16:14 ` [patch 5.15.y 0/2] rtmutex/futex: Backport of rejecting fixes Thomas Gleixner
2026-07-22 16:14   ` [patch 5.15.y 1/2] rtmutex: Use waiter::task instead of current in remove_waiter() Thomas Gleixner
2026-07-22 16:15   ` [patch 5.15.y 2/2] locking/rtmutex: Skip remove_waiter() when waiter is not enqueued Thomas Gleixner

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.