* FAILED: patch "[PATCH] futex: Avoid private hash use-after-free on final put" failed to apply to 6.18-stable tree
@ 2026-08-24 10:51 gregkh
2026-08-25 15:33 ` [PATCH 6.18.y 1/2] futex: Make futex_mm_init() void Sasha Levin
0 siblings, 1 reply; 3+ messages in thread
From: gregkh @ 2026-08-24 10:51 UTC (permalink / raw)
To: f3lix.dev, peterz; +Cc: stable
The patch below does not apply to the 6.18-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-6.18.y
git checkout FETCH_HEAD
git cherry-pick -x 1c7efabfbaf796f11000a46094a69955a01ec6cc
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<stable@vger.kernel.org>' --in-reply-to '2026082454-obligate-cultivate-908c@gregkh' --subject-prefix 'PATCH 6.18.y' 'HEAD^..'
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 1c7efabfbaf796f11000a46094a69955a01ec6cc Mon Sep 17 00:00:00 2001
From: Felix Hoffmann <f3lix.dev@gmx.de>
Date: Fri, 31 Jul 2026 17:50:24 +0200
Subject: [PATCH] futex: Avoid private hash use-after-free on final put
futex_private_hash_put() drops the reference to fph before evaluating
fph->mm for wake_up_var(). futex_ref_put() enables preemption again before
returning. If that put drops the final reference and the task is preempted,
another task can pivot to the replacement hash and free the old hash after
an RCU grace period. The first task then reads fph->mm from the freed
allocation when it resumes.
KASAN reports a slab-use-after-free in futex_private_hash_put(), with the
read at offset 24 in a freed kmalloc-512 allocation. The allocation and
free stacks point to futex_hash_allocate() and the RCU free path,
respectively.
Load the mm pointer while the fph reference is still held and pass the
saved value to wake_up_var(). wake_up_var() uses the pointer as a waitqueue
key and does not dereference the mm through it.
Fixes: bd54df5ea7ca ("futex: Allow to resize the private local hash")
Signed-off-by: Felix Hoffmann <f3lix.dev@gmx.de>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Cc: stable@vger.kernel.org
Link: https://patch.msgid.link/20260731155024.1150011-1-f3lix.dev@gmx.de
diff --git a/kernel/futex/core.c b/kernel/futex/core.c
index 0864c6e8cde7..d3fcad4ee716 100644
--- a/kernel/futex/core.c
+++ b/kernel/futex/core.c
@@ -139,8 +139,14 @@ static bool futex_private_hash_get(struct futex_private_hash *fph)
void futex_private_hash_put(struct futex_private_hash *fph)
{
- if (fph && futex_ref_put(fph))
- wake_up_var(fph->mm);
+ struct mm_struct *mm;
+
+ if (!fph)
+ return;
+
+ mm = fph->mm;
+ if (futex_ref_put(fph))
+ wake_up_var(mm);
}
static struct futex_hash_bucket *
^ permalink raw reply related [flat|nested] 3+ messages in thread
* [PATCH 6.18.y 1/2] futex: Make futex_mm_init() void
2026-08-24 10:51 FAILED: patch "[PATCH] futex: Avoid private hash use-after-free on final put" failed to apply to 6.18-stable tree gregkh
@ 2026-08-25 15:33 ` Sasha Levin
2026-08-25 15:33 ` [PATCH 6.18.y 2/2] futex: Avoid private hash use-after-free on final put Sasha Levin
0 siblings, 1 reply; 3+ messages in thread
From: Sasha Levin @ 2026-08-25 15:33 UTC (permalink / raw)
To: stable; +Cc: Thomas Gleixner, Peter Zijlstra (Intel), Sasha Levin
From: Thomas Gleixner <tglx@kernel.org>
[ Upstream commit d7b3f52c861f54ba2fff15696d3798277fb4c19f ]
Nothing fails there. Mop up the leftovers of the early version of this,
which did an allocation.
While at it clean up the stubs and the #ifdef comments to make the header
file readable.
Signed-off-by: Thomas Gleixner <tglx@kernel.org>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Link: https://patch.msgid.link/20260602090535.356789395@kernel.org
Stable-dep-of: 1c7efabfbaf7 ("futex: Avoid private hash use-after-free on final put")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
include/linux/futex.h | 28 +++++++++++-----------------
kernel/fork.c | 8 ++------
kernel/futex/core.c | 3 +--
3 files changed, 14 insertions(+), 25 deletions(-)
diff --git a/include/linux/futex.h b/include/linux/futex.h
index 9e9750f049805..87559766319e1 100644
--- a/include/linux/futex.h
+++ b/include/linux/futex.h
@@ -85,22 +85,20 @@ int futex_hash_prctl(unsigned long arg2, unsigned long arg3, unsigned long arg4)
#ifdef CONFIG_FUTEX_PRIVATE_HASH
int futex_hash_allocate_default(void);
void futex_hash_free(struct mm_struct *mm);
-int futex_mm_init(struct mm_struct *mm);
-
-#else /* !CONFIG_FUTEX_PRIVATE_HASH */
+void futex_mm_init(struct mm_struct *mm);
+#else /* CONFIG_FUTEX_PRIVATE_HASH */
static inline int futex_hash_allocate_default(void) { return 0; }
static inline int futex_hash_free(struct mm_struct *mm) { return 0; }
-static inline int futex_mm_init(struct mm_struct *mm) { return 0; }
-#endif /* CONFIG_FUTEX_PRIVATE_HASH */
+static inline void futex_mm_init(struct mm_struct *mm) { }
+#endif /* !CONFIG_FUTEX_PRIVATE_HASH */
-#else /* !CONFIG_FUTEX */
+#else /* CONFIG_FUTEX */
static inline void futex_init_task(struct task_struct *tsk) { }
static inline void futex_exit_recursive(struct task_struct *tsk) { }
static inline void futex_exit_release(struct task_struct *tsk) { }
static inline void futex_exec_release(struct task_struct *tsk) { }
-static inline long do_futex(u32 __user *uaddr, int op, u32 val,
- ktime_t *timeout, u32 __user *uaddr2,
- u32 val2, u32 val3)
+static inline long do_futex(u32 __user *uaddr, int op, u32 val, ktime_t *timeout,
+ u32 __user *uaddr2, u32 val2, u32 val3)
{
return -EINVAL;
}
@@ -108,13 +106,9 @@ static inline int futex_hash_prctl(unsigned long arg2, unsigned long arg3, unsig
{
return -EINVAL;
}
-static inline int futex_hash_allocate_default(void)
-{
- return 0;
-}
+static inline int futex_hash_allocate_default(void) { return 0; }
static inline int futex_hash_free(struct mm_struct *mm) { return 0; }
-static inline int futex_mm_init(struct mm_struct *mm) { return 0; }
+static inline void futex_mm_init(struct mm_struct *mm) { }
+#endif /* !CONFIG_FUTEX */
-#endif
-
-#endif
+#endif /* _LINUX_FUTEX_H */
diff --git a/kernel/fork.c b/kernel/fork.c
index 91f1512a1d312..ccddeba6790a4 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -1062,6 +1062,7 @@ static struct mm_struct *mm_init(struct mm_struct *mm, struct task_struct *p,
#endif
mm_init_uprobes_state(mm);
hugetlb_count_init(mm);
+ futex_mm_init(mm);
mm_flags_clear_all(mm);
if (current->mm) {
@@ -1074,11 +1075,8 @@ static struct mm_struct *mm_init(struct mm_struct *mm, struct task_struct *p,
mm->def_flags = 0;
}
- if (futex_mm_init(mm))
- goto fail_mm_init;
-
if (mm_alloc_pgd(mm))
- goto fail_nopgd;
+ goto fail_mm_init;
if (mm_alloc_id(mm))
goto fail_noid;
@@ -1105,8 +1103,6 @@ static struct mm_struct *mm_init(struct mm_struct *mm, struct task_struct *p,
mm_free_id(mm);
fail_noid:
mm_free_pgd(mm);
-fail_nopgd:
- futex_hash_free(mm);
fail_mm_init:
free_mm(mm);
return NULL;
diff --git a/kernel/futex/core.c b/kernel/futex/core.c
index fde558fd2bd60..f43d8c9e28a66 100644
--- a/kernel/futex/core.c
+++ b/kernel/futex/core.c
@@ -1747,7 +1747,7 @@ static bool futex_ref_is_dead(struct futex_private_hash *fph)
return atomic_long_read(&mm->futex_atomic) == 0;
}
-int futex_mm_init(struct mm_struct *mm)
+void futex_mm_init(struct mm_struct *mm)
{
mutex_init(&mm->futex_hash_lock);
RCU_INIT_POINTER(mm->futex_phash, NULL);
@@ -1756,7 +1756,6 @@ int futex_mm_init(struct mm_struct *mm)
mm->futex_ref = NULL;
atomic_long_set(&mm->futex_atomic, 0);
mm->futex_batches = get_state_synchronize_rcu();
- return 0;
}
void futex_hash_free(struct mm_struct *mm)
--
2.53.0
^ permalink raw reply related [flat|nested] 3+ messages in thread
* [PATCH 6.18.y 2/2] futex: Avoid private hash use-after-free on final put
2026-08-25 15:33 ` [PATCH 6.18.y 1/2] futex: Make futex_mm_init() void Sasha Levin
@ 2026-08-25 15:33 ` Sasha Levin
0 siblings, 0 replies; 3+ messages in thread
From: Sasha Levin @ 2026-08-25 15:33 UTC (permalink / raw)
To: stable; +Cc: Felix Hoffmann, Peter Zijlstra (Intel), Sasha Levin
From: Felix Hoffmann <f3lix.dev@gmx.de>
[ Upstream commit 1c7efabfbaf796f11000a46094a69955a01ec6cc ]
futex_private_hash_put() drops the reference to fph before evaluating
fph->mm for wake_up_var(). futex_ref_put() enables preemption again before
returning. If that put drops the final reference and the task is preempted,
another task can pivot to the replacement hash and free the old hash after
an RCU grace period. The first task then reads fph->mm from the freed
allocation when it resumes.
KASAN reports a slab-use-after-free in futex_private_hash_put(), with the
read at offset 24 in a freed kmalloc-512 allocation. The allocation and
free stacks point to futex_hash_allocate() and the RCU free path,
respectively.
Load the mm pointer while the fph reference is still held and pass the
saved value to wake_up_var(). wake_up_var() uses the pointer as a waitqueue
key and does not dereference the mm through it.
Fixes: bd54df5ea7ca ("futex: Allow to resize the private local hash")
Signed-off-by: Felix Hoffmann <f3lix.dev@gmx.de>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Cc: stable@vger.kernel.org
Link: https://patch.msgid.link/20260731155024.1150011-1-f3lix.dev@gmx.de
[ dropped the `!fph` NULL guard since this tree's callers already check, keeping the existing `if (futex_ref_put(fph))` form ]
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
kernel/futex/core.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/kernel/futex/core.c b/kernel/futex/core.c
index f43d8c9e28a66..cf9a11c763c6d 100644
--- a/kernel/futex/core.c
+++ b/kernel/futex/core.c
@@ -149,8 +149,10 @@ static bool futex_private_hash_get(struct futex_private_hash *fph)
void futex_private_hash_put(struct futex_private_hash *fph)
{
+ struct mm_struct *mm = fph->mm;
+
if (futex_ref_put(fph))
- wake_up_var(fph->mm);
+ wake_up_var(mm);
}
/**
--
2.53.0
^ permalink raw reply related [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-08-25 15:33 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-24 10:51 FAILED: patch "[PATCH] futex: Avoid private hash use-after-free on final put" failed to apply to 6.18-stable tree gregkh
2026-08-25 15:33 ` [PATCH 6.18.y 1/2] futex: Make futex_mm_init() void Sasha Levin
2026-08-25 15:33 ` [PATCH 6.18.y 2/2] futex: Avoid private hash use-after-free on final put Sasha Levin
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox