mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: "tip-bot2 for Thomas Gleixner" <tip-bot2@linutronix.de>
To: linux-tip-commits@vger.kernel.org
Cc: Thomas Gleixner <tglx@kernel.org>,
	"Peter Zijlstra (Intel)" <peterz@infradead.org>,
	andrealmeid@igalia.com, x86@kernel.org,
	linux-kernel@vger.kernel.org
Subject: [tip: locking/core] futex: Add robust futex unlock IP range
Date: Wed, 03 Jun 2026 14:24:54 -0000	[thread overview]
Message-ID: <178049669466.710.16541586267709807109.tip-bot2@tip-bot2> (raw)
In-Reply-To: <20260602090535.718926819@kernel.org>

The following commit has been merged into the locking/core branch of tip:

Commit-ID:     042df0c1d48609a85580dcbaff498c95ced20a5f
Gitweb:        https://git.kernel.org/tip/042df0c1d48609a85580dcbaff498c95ced20a5f
Author:        Thomas Gleixner <tglx@kernel.org>
AuthorDate:    Tue, 02 Jun 2026 11:09:59 +02:00
Committer:     Peter Zijlstra <peterz@infradead.org>
CommitterDate: Wed, 03 Jun 2026 11:38:51 +02:00

futex: Add robust futex unlock IP range

There will be a VDSO function to unlock robust futexes in user space. The
unlock sequence is racy vs. clearing the list_pending_op pointer in the
tasks robust list head. To plug this race the kernel needs to know the
instruction window. As the VDSO is per MM the addresses are stored in
mm_struct::futex.

Architectures which implement support for this have to update these
addresses when the VDSO is (re)mapped and indicate the pending op pointer
size which is matching the IP.

Arguably this could be resolved by chasing mm->context->vdso->image, but
that's architecture specific and requires to touch quite some cache
lines. Having it in mm::futex reduces the cache line impact and avoids
having yet another set of architecture specific functionality.

To support multi size robust list applications (gaming) this provides two
ranges when COMPAT is enabled.

Signed-off-by: Thomas Gleixner <tglx@kernel.org>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: André Almeida <andrealmeid@igalia.com>
Link: https://patch.msgid.link/20260602090535.718926819@kernel.org
---
 include/linux/futex.h       | 21 +++++++++++++---
 include/linux/futex_types.h | 28 ++++++++++++++++++++++-
 init/Kconfig                |  6 +++++-
 kernel/futex/core.c         | 46 ++++++++++++++++++++++++++++--------
 4 files changed, 89 insertions(+), 12 deletions(-)

diff --git a/include/linux/futex.h b/include/linux/futex.h
index 9e6218c..cb2a182 100644
--- a/include/linux/futex.h
+++ b/include/linux/futex.h
@@ -81,11 +81,9 @@ 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);
-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 void futex_mm_init(struct mm_struct *mm) { }
 #endif /* !CONFIG_FUTEX_PRIVATE_HASH */
 
 #else  /* CONFIG_FUTEX */
@@ -104,7 +102,24 @@ static inline int futex_hash_prctl(unsigned long arg2, unsigned long arg3, unsig
 }
 static inline int futex_hash_allocate_default(void) { return 0; }
 static inline int futex_hash_free(struct mm_struct *mm) { return 0; }
-static inline void futex_mm_init(struct mm_struct *mm) { }
 #endif /* !CONFIG_FUTEX */
 
+#ifdef CONFIG_FUTEX_ROBUST_UNLOCK
+void futex_reset_cs_ranges(struct futex_mm_data *fd);
+
+static inline void futex_set_vdso_cs_range(struct futex_mm_data *fd, unsigned int idx,
+					   unsigned long start, unsigned long end, bool sz32)
+{
+	fd->unlock.cs_ranges[idx].start_ip = start;
+	fd->unlock.cs_ranges[idx].len = end - start;
+	fd->unlock.cs_ranges[idx].pop_size32 = sz32;
+}
+#endif /* CONFIG_FUTEX_ROBUST_UNLOCK */
+
+#if defined(CONFIG_FUTEX_PRIVATE_HASH) || defined(CONFIG_FUTEX_ROBUST_UNLOCK)
+void futex_mm_init(struct mm_struct *mm);
+#else
+static inline void futex_mm_init(struct mm_struct *mm) { }
+#endif
+
 #endif /* _LINUX_FUTEX_H */
diff --git a/include/linux/futex_types.h b/include/linux/futex_types.h
index d41557d..d320c05 100644
--- a/include/linux/futex_types.h
+++ b/include/linux/futex_types.h
@@ -55,12 +55,40 @@ struct futex_mm_phash {
 struct futex_mm_phash { };
 #endif /* !CONFIG_FUTEX_ROBUST_UNLOCK */
 
+#ifdef CONFIG_FUTEX_ROBUST_UNLOCK
+/**
+ * struct futex_unlock_cs_range - Range for the VDSO unlock critical section
+ * @start_ip:	The start IP of the robust futex unlock critical section (inclusive)
+ * @len:	The length of the robust futex unlock critical section
+ * @pop_size32:	Pending OP pointer size indicator. 0 == 64-bit, 1 == 32-bit
+ */
+struct futex_unlock_cs_range {
+	unsigned long	       start_ip;
+	unsigned int	       len;
+	unsigned int	       pop_size32;
+};
+
+#define FUTEX_ROBUST_MAX_CS_RANGES	(1 + IS_ENABLED(CONFIG_COMPAT))
+
+/**
+ * struct futex_unlock_cs_ranges - Futex unlock VSDO critical sections
+ * @cs_ranges:	Array of critical section ranges
+ */
+struct futex_unlock_cs_ranges {
+	struct futex_unlock_cs_range	cs_ranges[FUTEX_ROBUST_MAX_CS_RANGES];
+};
+#else  /* CONFIG_FUTEX_ROBUST_UNLOCK */
+struct futex_unlock_cs_ranges { };
+#endif /* !CONFIG_FUTEX_ROBUST_UNLOCK */
+
 /**
  * struct futex_mm_data - Futex related per MM data
  * @phash:	Futex private hash related data
+ * @unlock:	Futex unlock VDSO critical sections
  */
 struct futex_mm_data {
 	struct futex_mm_phash		phash;
+	struct futex_unlock_cs_ranges	unlock;
 };
 #else  /* CONFIG_FUTEX */
 struct futex_sched_data { };
diff --git a/init/Kconfig b/init/Kconfig
index 2937c4d..165b08e 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -1842,6 +1842,12 @@ config FUTEX_MPOL
 	depends on FUTEX && NUMA
 	default y
 
+config HAVE_FUTEX_ROBUST_UNLOCK
+	bool
+
+config FUTEX_ROBUST_UNLOCK
+	def_bool FUTEX && HAVE_GENERIC_VDSO && GENERIC_IRQ_ENTRY && RSEQ && HAVE_FUTEX_ROBUST_UNLOCK
+
 config EPOLL
 	bool "Enable eventpoll support" if EXPERT
 	default y
diff --git a/kernel/futex/core.c b/kernel/futex/core.c
index 77ccb77..aad6e50 100644
--- a/kernel/futex/core.c
+++ b/kernel/futex/core.c
@@ -1761,11 +1761,11 @@ static bool futex_ref_is_dead(struct futex_private_hash *fph)
 	return atomic_long_read(&mm->futex.phash.atomic) == 0;
 }
 
-void futex_mm_init(struct mm_struct *mm)
+static void futex_hash_init_mm(struct futex_mm_data *fd)
 {
-	memset(&mm->futex, 0, sizeof(mm->futex));
-	mutex_init(&mm->futex.phash.lock);
-	mm->futex.phash.batches = get_state_synchronize_rcu();
+	memset(&fd->phash, 0, sizeof(fd->phash));
+	mutex_init(&fd->phash.lock);
+	fd->phash.batches = get_state_synchronize_rcu();
 }
 
 void futex_hash_free(struct mm_struct *mm)
@@ -1969,19 +1969,47 @@ static int futex_hash_get_slots(void)
 		return fph->hash_mask + 1;
 	return 0;
 }
+#else  /* CONFIG_FUTEX_PRIVATE_HASH */
+static inline int futex_hash_allocate(unsigned int hslots, unsigned int flags) { return -EINVAL; }
+static inline int futex_hash_get_slots(void) { return 0; }
+static inline void futex_hash_init_mm(struct futex_mm_data *fd) { }
+#endif /* !CONFIG_FUTEX_PRIVATE_HASH */
 
-#else
+#ifdef CONFIG_FUTEX_ROBUST_UNLOCK
+static void futex_invalidate_cs_ranges(struct futex_mm_data *fd)
+{
+	/*
+	 * Invalidate start_ip so that the quick check fails for ip >= start_ip
+	 * if VDSO is not mapped or the second slot is not available for compat
+	 * tasks as they use VDSO32 which does not provide the 64-bit pointer
+	 * variant.
+	 */
+	for (int i = 0; i < FUTEX_ROBUST_MAX_CS_RANGES; i++)
+		fd->unlock.cs_ranges[i].start_ip = ~0UL;
+}
 
-static int futex_hash_allocate(unsigned int hash_slots, unsigned int flags)
+void futex_reset_cs_ranges(struct futex_mm_data *fd)
 {
-	return -EINVAL;
+	memset(fd->unlock.cs_ranges, 0, sizeof(fd->unlock.cs_ranges));
+	futex_invalidate_cs_ranges(fd);
 }
 
-static int futex_hash_get_slots(void)
+static void futex_robust_unlock_init_mm(struct futex_mm_data *fd)
 {
-	return 0;
+	/* mm_dup() preserves the range, mm_alloc() clears it */
+	if (!fd->unlock.cs_ranges[0].start_ip)
+		futex_invalidate_cs_ranges(fd);
 }
+#else  /* CONFIG_FUTEX_ROBUST_UNLOCK */
+static inline void futex_robust_unlock_init_mm(struct futex_mm_data *fd) { }
+#endif /* !CONFIG_FUTEX_ROBUST_UNLOCK */
 
+#if defined(CONFIG_FUTEX_PRIVATE_HASH) || defined(CONFIG_FUTEX_ROBUST_UNLOCK)
+void futex_mm_init(struct mm_struct *mm)
+{
+	futex_hash_init_mm(&mm->futex);
+	futex_robust_unlock_init_mm(&mm->futex);
+}
 #endif
 
 int futex_hash_prctl(unsigned long arg2, unsigned long arg3, unsigned long arg4)

  reply	other threads:[~2026-06-03 14:24 UTC|newest]

Thread overview: 44+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-06-02  9:09 [patch V5 00/16] futex: Address the robust futex unlock race for real Thomas Gleixner
2026-06-02  9:09 ` [patch V5 01/16] percpu: Sanitize __percpu_qual include hell Thomas Gleixner
2026-06-03 14:25   ` [tip: locking/core] " tip-bot2 for Thomas Gleixner
2026-06-02  9:09 ` [patch V5 02/16] futex: Move futex task related data into a struct Thomas Gleixner
2026-06-03 14:25   ` [tip: locking/core] " tip-bot2 for Thomas Gleixner
2026-06-02  9:09 ` [patch V5 03/16] futex: Make futex_mm_init() void Thomas Gleixner
2026-06-03 14:25   ` [tip: locking/core] " tip-bot2 for Thomas Gleixner
2026-06-02  9:09 ` [patch V5 04/16] futex: Move futex related mm_struct data into a struct Thomas Gleixner
2026-06-03 14:25   ` [tip: locking/core] " tip-bot2 for Thomas Gleixner
2026-06-02  9:09 ` [patch V5 05/16] futex: Provide UABI defines for robust list entry modifiers Thomas Gleixner
2026-06-03 14:25   ` [tip: locking/core] " tip-bot2 for Thomas Gleixner
2026-06-02  9:09 ` [patch V5 06/16] uaccess: Provide unsafe_atomic_store_release_user() Thomas Gleixner
2026-06-03 14:24   ` [tip: locking/core] " tip-bot2 for Thomas Gleixner
2026-06-02  9:09 ` [patch V5 07/16] x86: Select ARCH_MEMORY_ORDER_TSO Thomas Gleixner
2026-06-03 14:24   ` [tip: locking/core] " tip-bot2 for Thomas Gleixner
2026-06-02  9:09 ` [patch V5 08/16] futex: Cleanup UAPI defines Thomas Gleixner
2026-06-03 14:24   ` [tip: locking/core] " tip-bot2 for Thomas Gleixner
2026-06-04  8:23   ` [patch V5 08/16] " David Laight
2026-06-02  9:09 ` [patch V5 09/16] futex: Add support for unlocking robust futexes Thomas Gleixner
2026-06-03  8:22   ` Peter Zijlstra
2026-06-03  9:30     ` Peter Zijlstra
2026-06-03 14:40     ` Thomas Gleixner
2026-06-03  8:35   ` Peter Zijlstra
2026-06-03 14:24   ` [tip: locking/core] " tip-bot2 for Thomas Gleixner
2026-06-02  9:09 ` [patch V5 10/16] futex: Add robust futex unlock IP range Thomas Gleixner
2026-06-03 14:24   ` tip-bot2 for Thomas Gleixner [this message]
2026-06-02  9:10 ` [patch V5 11/16] futex: Provide infrastructure to plug the non contended robust futex unlock race Thomas Gleixner
2026-06-03  8:42   ` Peter Zijlstra
2026-06-03  9:14   ` Peter Zijlstra
2026-06-03 14:47     ` Thomas Gleixner
2026-06-03  9:23   ` Peter Zijlstra
2026-06-03 14:42     ` Thomas Gleixner
2026-06-03 14:24   ` [tip: locking/core] " tip-bot2 for Thomas Gleixner
2026-06-02  9:10 ` [patch V5 12/16] x86/vdso: Prepare for robust futex unlock support Thomas Gleixner
2026-06-03 14:24   ` [tip: locking/core] " tip-bot2 for Thomas Gleixner
2026-06-02  9:10 ` [patch V5 13/16] x86/vdso: Implement __vdso_futex_robust_try_unlock() Thomas Gleixner
2026-06-03 14:24   ` [tip: locking/core] " tip-bot2 for Thomas Gleixner
2026-06-02  9:10 ` [patch V5 14/16] Documentation: futex: Add a note about robust list race condition Thomas Gleixner
2026-06-03 14:24   ` [tip: locking/core] " tip-bot2 for André Almeida
2026-06-02  9:10 ` [patch V5 15/16] selftests: futex: Add tests for robust release operations Thomas Gleixner
2026-06-03 14:24   ` [tip: locking/core] " tip-bot2 for André Almeida
2026-06-02  9:10 ` [patch V5 16/16] [RFC] vdso, x86: Expose vdso.so.dbg through sysfs Thomas Gleixner
2026-06-02 10:39   ` Thomas Weißschuh
2026-06-02 20:02     ` Thomas Gleixner

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=178049669466.710.16541586267709807109.tip-bot2@tip-bot2 \
    --to=tip-bot2@linutronix.de \
    --cc=andrealmeid@igalia.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-tip-commits@vger.kernel.org \
    --cc=peterz@infradead.org \
    --cc=tglx@kernel.org \
    --cc=x86@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®