* FAILED: patch "[PATCH] futex/requeue: Prevent NULL pointer dereference in" failed to apply to 5.10-stable tree
@ 2026-07-21 15:13 gregkh
2026-07-22 15:13 ` Thomas Gleixner
2026-07-22 16:14 ` [patch 5.10.y 0/2] rtmutex/futex: Backport of rejecting fixes Thomas Gleixner
0 siblings, 2 replies; 5+ 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.10-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.10.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-striking-reaffirm-3311@gregkh' --subject-prefix 'PATCH 5.10.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] 5+ messages in thread* Re: FAILED: patch "[PATCH] futex/requeue: Prevent NULL pointer dereference in" failed to apply to 5.10-stable tree
2026-07-21 15:13 FAILED: patch "[PATCH] futex/requeue: Prevent NULL pointer dereference in" failed to apply to 5.10-stable tree gregkh
@ 2026-07-22 15:13 ` Thomas Gleixner
2026-07-22 16:14 ` [patch 5.10.y 0/2] rtmutex/futex: Backport of rejecting fixes Thomas Gleixner
1 sibling, 0 replies; 5+ messages in thread
From: Thomas Gleixner @ 2026-07-22 15:13 UTC (permalink / raw)
To: gregkh, eilaimemedsnaimel; +Cc: stable
On Tue, Jul 21 2026 at 17:13, gregkh@linuxfoundation.org wrote:
> The patch below does not apply to the 5.10-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.10.y
> git checkout FETCH_HEAD
> git cherry-pick -x 74e144274af39935b0f410c0ee4d2b91c3730414
As I said before this commit should not be backported as it is buggy and
got reverted upstream:
39def6d250d3 ("futex/requeue: Revert "Prevent NULL pointer dereference in remove_waiter() on self-deadlock""")
The one which fixes the actual problem is:
40a25d59e85b ("locking/rtmutex: Skip remove_waiter() when waiter is not enqueued")
That one does not apply to 5.10/15 either as the prerequisite
3bfdc63936dd ("rtmutex: Use waiter::task instead of current in remove_waiter()")
has not been backported presumably because the Fixes tag in that commit
points to a commit which got introduced post 5.15. Though the bug it
fixes got introduced way earlier.
Let me backport these two:
3bfdc63936dd ("rtmutex: Use waiter::task instead of current in remove_waiter()")
40a25d59e85b ("locking/rtmutex: Skip remove_waiter() when waiter is not enqueued")
to 5.10.y and 5.15.y. I'll send a series later.
Thanks,
tglx
^ permalink raw reply [flat|nested] 5+ messages in thread* [patch 5.10.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.10-stable tree gregkh
2026-07-22 15:13 ` Thomas Gleixner
@ 2026-07-22 16:14 ` Thomas Gleixner
2026-07-22 16:14 ` [patch 5.10.y 1/2] rtmutex: Use waiter::task instead of current in remove_waiter() Thomas Gleixner
2026-07-22 16:14 ` [patch 5.10.y 2/2] locking/rtmutex: Skip remove_waiter() when waiter is not enqueued Thomas Gleixner
1 sibling, 2 replies; 5+ 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.10.y. 5.15.y needs another tiny tweak and comes separate.
Thanks,
tglx
^ permalink raw reply [flat|nested] 5+ messages in thread* [patch 5.10.y 1/2] rtmutex: Use waiter::task instead of current in remove_waiter()
2026-07-22 16:14 ` [patch 5.10.y 0/2] rtmutex/futex: Backport of rejecting fixes Thomas Gleixner
@ 2026-07-22 16:14 ` Thomas Gleixner
2026-07-22 16:14 ` [patch 5.10.y 2/2] locking/rtmutex: Skip remove_waiter() when waiter is not enqueued Thomas Gleixner
1 sibling, 0 replies; 5+ messages in thread
From: Thomas Gleixner @ 2026-07-22 16:14 UTC (permalink / raw)
To: stable; +Cc: tglx
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 | 13 ++++++++-----
1 file changed, 8 insertions(+), 5 deletions(-)
---
--- a/kernel/locking/rtmutex.c
+++ b/kernel/locking/rtmutex.c
@@ -1059,22 +1059,25 @@ static void mark_wakeup_next_waiter(stru
/*
* Remove a waiter from a lock and give up
*
- * Must be called with lock->wait_lock held and interrupts disabled. I must
+ * 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 remove_waiter(struct rt_mutex *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 *next_lock;
lockdep_assert_held(&lock->wait_lock);
- raw_spin_lock(¤t->pi_lock);
+ raw_spin_lock(&waiter_task->pi_lock);
rt_mutex_dequeue(lock, waiter);
- current->pi_blocked_on = NULL;
- raw_spin_unlock(¤t->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
@@ -1110,7 +1113,7 @@ static void remove_waiter(struct rt_mute
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] 5+ messages in thread* [patch 5.10.y 2/2] locking/rtmutex: Skip remove_waiter() when waiter is not enqueued
2026-07-22 16:14 ` [patch 5.10.y 0/2] rtmutex/futex: Backport of rejecting fixes Thomas Gleixner
2026-07-22 16:14 ` [patch 5.10.y 1/2] rtmutex: Use waiter::task instead of current in remove_waiter() Thomas Gleixner
@ 2026-07-22 16:14 ` Thomas Gleixner
1 sibling, 0 replies; 5+ messages in thread
From: Thomas Gleixner @ 2026-07-22 16:14 UTC (permalink / raw)
To: stable; +Cc: tglx
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 | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
---
--- a/kernel/locking/rtmutex.c
+++ b/kernel/locking/rtmutex.c
@@ -1074,6 +1074,9 @@ static void remove_waiter(struct rt_mute
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;
@@ -1803,7 +1806,7 @@ int rt_mutex_start_proxy_lock(struct rt_
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] 5+ messages in thread
end of thread, other threads:[~2026-07-22 16:14 UTC | newest]
Thread overview: 5+ 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.10-stable tree gregkh
2026-07-22 15:13 ` Thomas Gleixner
2026-07-22 16:14 ` [patch 5.10.y 0/2] rtmutex/futex: Backport of rejecting fixes Thomas Gleixner
2026-07-22 16:14 ` [patch 5.10.y 1/2] rtmutex: Use waiter::task instead of current in remove_waiter() Thomas Gleixner
2026-07-22 16:14 ` [patch 5.10.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.