[PATCH] futex: Temporarily set the task state to running for pivot pending
From: Edward Adam Davis
Date: Mon Aug 17 2026 - 01:33:18 EST
There is a report of futex_pivot_pending() locking a mutex while not
TASK_RUNNING, which is due to wait_var_event(mm, futex_pivot_pending(mm))
calls __wait_var_event(), which sets the current task state to 2 before
the condition function `futex_pivot_pending()` executes, which triggers
the warning in [1].
Temporarily set the current task state to 0 within futex_pivot_pending()
to allow `mmph->lock` to complete its lifecycle normally.
[1]
do not call blocking ops when !TASK_RUNNING; state=2 set at [<000000003d62a0c3>] prepare_to_wait_event+0x2e4/0x3ac kernel/sched/wait.c:-1
WARNING: kernel/sched/core.c:9124 at __might_sleep+0xc0/0xdc kernel/sched/core.c:9120, CPU#0: syz.0.17/4920
Call trace:
class_mutex_constructor include/linux/mutex.h:253 [inline]
futex_pivot_pending+0x30/0xa4 kernel/futex/core.c:1789
futex_hash_allocate+0x73c/0xc20 kernel/futex/core.c:1872
futex_hash_prctl+0xd0/0x324 kernel/futex/core.c:2027
Fixes: 8e7ff730dd96 ("futex: Fix race in futex_pivot_pending() during private hash resize")
Reported-by: syzbot+9c28ada89c468ad30713@xxxxxxxxxxxxxxxxxxxxxxxxx
Closes: https://syzkaller.appspot.com/bug?extid=9c28ada89c468ad30713
Tested-by: syzbot+9c28ada89c468ad30713@xxxxxxxxxxxxxxxxxxxxxxxxx
Signed-off-by: Edward Adam Davis <eadavis@xxxxxx>
---
kernel/futex/core.c | 22 ++++++++++++++++------
1 file changed, 16 insertions(+), 6 deletions(-)
diff --git a/kernel/futex/core.c b/kernel/futex/core.c
index 128c5752f225..a0b17d2f41da 100644
--- a/kernel/futex/core.c
+++ b/kernel/futex/core.c
@@ -1785,14 +1785,24 @@ static bool futex_pivot_pending(struct mm_struct *mm)
{
struct futex_mm_phash *mmph = &mm->futex.phash;
struct futex_private_hash *fph;
+ unsigned int state;
+ bool ret;
+
+ state = current->__state;
+ __set_current_state(TASK_RUNNING);
+ scoped_guard(mutex, &mmph->lock) {
+ if (!mmph->hash_new) {
+ ret = true;
+ goto out;
+ }
- guard(mutex)(&mmph->lock);
-
- if (!mmph->hash_new)
- return true;
+ fph = rcu_dereference_raw(mmph->hash);
+ ret = futex_ref_is_dead(fph);
+ }
+out:
+ __set_current_state(state);
+ return ret;
- fph = rcu_dereference_raw(mmph->hash);
- return futex_ref_is_dead(fph);
}
static bool futex_hash_less(struct futex_private_hash *a,
--
2.43.0