mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH v8 00/10] futex: Create {set,get}_robust_list2() syscalls
@ 2026-11-15 17:31 André Almeida
  2026-11-15 17:31 ` [PATCH v8 01/10] futex: Skip test_futex_robust_unlock() if not supported André Almeida
                   ` (9 more replies)
  0 siblings, 10 replies; 14+ messages in thread
From: André Almeida @ 2026-11-15 17:31 UTC (permalink / raw)
  To: Ingo Molnar, Peter Zijlstra, Darren Hart, Davidlohr Bueso,
	Arnd Bergmann, Sebastian Andrzej Siewior, Waiman Long,
	Ryan Houdek, Thomas Gleixner
  Cc: linux-kernel, linux-kselftest, linux-api, kernel-dev, André Almeida

Hello,

Now that we mostly fixed the op_pending race condition, I believe it's time to
continue the new syscall work. This patchset is adapted to the robust_try_unlock
mechanics.

 * Use case

The use-case for the new syscalls is detailed in the last patch version:

  https://lore.kernel.org/lkml/20250626-tonyk-robust_futex-v5-0-179194dbde8f@igalia.com

 * The syscall interface

Documented at patches 3/9 "futex: Create set_robust_list2() syscall" and
4/9 "futex: Create get_robust_list2() syscall".

 * Testing

I expanded the current robust list selftest to use the new interface,
and also ported the original syscall to use the new syscall internals,
and everything survived the tests. Tested on both x86 and arm64.

 * Changelog

Changes from v7:
- Expanded the selftest for more corner cases and error handling
- Fix a lot of Sashiko findings, including:
- Refactor handling of 32-bit lists in get_robust_list2 
- Fix legacy 32-bit list creation overwritting 64-bit list
- Fix 32-bit list never getting cleared
- Fix corrupting error code
- Fix logic for modifying list elements
- Link to v7: https://patch.msgid.link/20260925-tonyk-robust_futex-v7-0-d1095991152c@igalia.com

Changes from v6:
 - Interface now uses CREATE/MODIFY semantics instead of SET. This allows to
 both libc and app to use the lists without conflicts.
 - Rebased on top of mainline, including the new VDSO changes
 - v6: https://lore.kernel.org/r/20251122-tonyk-robust_futex-v6-0-05fea005a0fd@igalia.com

Changes from v5:
 - Complete interface rewrite, there are so many changes but the main
   ones are the following points
 - Array of robust lists now has a static size, allocated once during the
   first usage of the list
 - Now that the list of robust lists have a fixed size, I removed the
   logic of having a command for creating a new index on the list. To
   simplify things for everyone, userspace just need to call
   set_robust_list2(head, 32-bit/64-bit type, index).
 - Created get_robust_list2()
 - The new code can be better integrated with the original interface
 - v5: https://lore.kernel.org/r/20250626-tonyk-robust_futex-v5-0-179194dbde8f@igalia.com

Feedback is very welcomed!

---
André Almeida (10):
      futex: Skip test_futex_robust_unlock() if not supported
      futex: Use explicit sizes for compat_robust_list structs
      futex: Make exit_robust_list32() unconditionally available for 64-bit kernels
      futex: Create set_robust_list2() syscall
      futex: Create get_robust_list2() syscall
      futex: Wire up set_robust_list2 syscall
      futex: Wire up get_robust_list2 syscall
      selftests/futex: Expand for set_robust_list2()
      selftests/futex: Expand for get_robust_list2()
      futex: Use new robust list API internally

 arch/alpha/kernel/syscalls/syscall.tbl             |   2 +
 arch/arm/tools/syscall.tbl                         |   2 +
 arch/m68k/kernel/syscalls/syscall.tbl              |   2 +
 arch/microblaze/kernel/syscalls/syscall.tbl        |   2 +
 arch/mips/kernel/syscalls/syscall_n32.tbl          |   2 +
 arch/mips/kernel/syscalls/syscall_n64.tbl          |   2 +
 arch/mips/kernel/syscalls/syscall_o32.tbl          |   2 +
 arch/parisc/kernel/syscalls/syscall.tbl            |   2 +
 arch/powerpc/kernel/syscalls/syscall.tbl           |   2 +
 arch/s390/kernel/syscalls/syscall.tbl              |   2 +
 arch/sh/kernel/syscalls/syscall.tbl                |   2 +
 arch/sparc/kernel/syscalls/syscall.tbl             |   2 +
 arch/x86/entry/syscalls/syscall_32.tbl             |   2 +
 arch/x86/entry/syscalls/syscall_64.tbl             |   2 +
 arch/xtensa/kernel/syscalls/syscall.tbl            |   2 +
 include/linux/compat.h                             |  13 +-
 include/linux/futex.h                              |  24 +
 include/linux/futex_types.h                        |   9 +-
 include/uapi/asm-generic/unistd.h                  |   7 +-
 include/uapi/linux/futex.h                         |  28 +
 kernel/futex/core.c                                | 196 +++++--
 kernel/futex/futex.h                               |   5 +
 kernel/futex/syscalls.c                            | 158 +++++-
 kernel/sys_ni.c                                    |   2 +
 scripts/syscall.tbl                                |   2 +
 .../selftests/futex/functional/robust_list.c       | 626 +++++++++++++++++++--
 26 files changed, 976 insertions(+), 124 deletions(-)
---
base-commit: 9f74092fda91ef93c2b07585785c1dc83cd7971f
change-id: 20250225-tonyk-robust_futex-60adeedac695

Best regards,
--  
André Almeida <andrealmeid@igalia.com>


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

* [PATCH v8 01/10] futex: Skip test_futex_robust_unlock() if not supported
  2026-11-15 17:31 [PATCH v8 00/10] futex: Create {set,get}_robust_list2() syscalls André Almeida
@ 2026-11-15 17:31 ` André Almeida
  2026-11-15 17:31 ` [PATCH v8 02/10] futex: Use explicit sizes for compat_robust_list structs André Almeida
                   ` (8 subsequent siblings)
  9 siblings, 0 replies; 14+ messages in thread
From: André Almeida @ 2026-11-15 17:31 UTC (permalink / raw)
  To: Ingo Molnar, Peter Zijlstra, Darren Hart, Davidlohr Bueso,
	Arnd Bergmann, Sebastian Andrzej Siewior, Waiman Long,
	Ryan Houdek, Thomas Gleixner
  Cc: linux-kernel, linux-kselftest, linux-api, kernel-dev, André Almeida

Skip test_futex_robust_unlock() if FUTEX_ROBUST_UNLOCK operation is not
supported.

Signed-off-by: André Almeida <andrealmeid@igalia.com>
---
 tools/testing/selftests/futex/functional/robust_list.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/tools/testing/selftests/futex/functional/robust_list.c b/tools/testing/selftests/futex/functional/robust_list.c
index 87217c549361..ddb610149857 100644
--- a/tools/testing/selftests/futex/functional/robust_list.c
+++ b/tools/testing/selftests/futex/functional/robust_list.c
@@ -792,6 +792,9 @@ TEST_F(futex_op, test_futex_robust_unlock)
 	ret = sys_futex_robust_unlock(futex, FUTEX_ROBUST_UNLOCK | variant->op, tid,
 				      &head.list_op_pending, variant->val3);
 
+	if (ret == -1 && errno == ENOSYS)
+		SKIP(return, "No support for FUTEX_ROBUST_UNLOCK");
+
 	ASSERT_EQ(ret, 0);
 	ASSERT_EQ(*futex, 0);
 

-- 
2.56.1


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

* [PATCH v8 02/10] futex: Use explicit sizes for compat_robust_list structs
  2026-11-15 17:31 [PATCH v8 00/10] futex: Create {set,get}_robust_list2() syscalls André Almeida
  2026-11-15 17:31 ` [PATCH v8 01/10] futex: Skip test_futex_robust_unlock() if not supported André Almeida
@ 2026-11-15 17:31 ` André Almeida
  2026-11-15 17:31 ` [PATCH v8 03/10] futex: Make exit_robust_list32() unconditionally available for 64-bit kernels André Almeida
                   ` (7 subsequent siblings)
  9 siblings, 0 replies; 14+ messages in thread
From: André Almeida @ 2026-11-15 17:31 UTC (permalink / raw)
  To: Ingo Molnar, Peter Zijlstra, Darren Hart, Davidlohr Bueso,
	Arnd Bergmann, Sebastian Andrzej Siewior, Waiman Long,
	Ryan Houdek, Thomas Gleixner
  Cc: linux-kernel, linux-kselftest, linux-api, kernel-dev, André Almeida

There are two functions for handling robust lists during a task exit:
exit_robust_list() and compat_exit_robust_list(). The first one handles
either 64-bit or 32-bit lists, depending on the kernel bitness.
compat_exit_robust_list() exists only in 64-bit kernels that supports
32-bit syscalls entry points (also known as compat entry points).

The new syscall set_robust_list2() needs to handle both 64-bit and
32-bit robust lists, regardless of compat entry being enabled, so it
needs to have both functions always available.

In preparation for this, use explicit size for struct members of
compat_robust_list and compat_robust_list_head. Rename the structs and
compat_exit_robust_list() to make clear which bitness it handles.

Keep exit_robust_list() as it is: used to handle the native bit size of
the kernel.

Signed-off-by: André Almeida <andrealmeid@igalia.com>
---
 include/linux/compat.h      | 13 +++----------
 include/linux/futex.h       |  4 ++++
 include/linux/futex_types.h |  5 ++---
 include/uapi/linux/futex.h  | 10 ++++++++++
 kernel/futex/core.c         | 33 +++++++++++++++++----------------
 kernel/futex/syscalls.c     |  9 +++++----
 6 files changed, 41 insertions(+), 33 deletions(-)

diff --git a/include/linux/compat.h b/include/linux/compat.h
index ad37ca617e65..77bfef1b3bd2 100644
--- a/include/linux/compat.h
+++ b/include/linux/compat.h
@@ -390,15 +390,8 @@ struct compat_ifconf {
 	compat_caddr_t  ifcbuf;
 };
 
-struct compat_robust_list {
-	compat_uptr_t			next;
-};
-
-struct compat_robust_list_head {
-	struct compat_robust_list	list;
-	compat_long_t			futex_offset;
-	compat_uptr_t			list_op_pending;
-};
+struct robust_list32;
+struct robust_list_head32;
 
 #ifdef CONFIG_COMPAT_OLD_SIGACTION
 struct compat_old_sigaction {
@@ -677,7 +670,7 @@ asmlinkage long compat_sys_waitid(int, compat_pid_t,
 		struct compat_siginfo __user *, int,
 		struct compat_rusage __user *);
 asmlinkage long
-compat_sys_set_robust_list(struct compat_robust_list_head __user *head,
+compat_sys_set_robust_list(struct robust_list_head32 __user *head,
 			   compat_size_t len);
 asmlinkage long
 compat_sys_get_robust_list(int pid, compat_uptr_t __user *head_ptr,
diff --git a/include/linux/futex.h b/include/linux/futex.h
index a895d8c69d66..93316876a4ee 100644
--- a/include/linux/futex.h
+++ b/include/linux/futex.h
@@ -72,6 +72,10 @@ static inline void futex_init_task(struct task_struct *tsk)
 	INIT_LIST_HEAD(&tsk->futex.pi_state_list);
 	tsk->futex.state = FUTEX_STATE_OK;
 	mutex_init(&tsk->futex.exit_mutex);
+	tsk->futex.robust_list = NULL;
+#ifdef CONFIG_COMPAT
+	tsk->futex.robust_list32 = NULL;
+#endif
 }
 
 void futex_exit_recursive(struct task_struct *tsk);
diff --git a/include/linux/futex_types.h b/include/linux/futex_types.h
index 34b16f2828e7..f58616d7e20b 100644
--- a/include/linux/futex_types.h
+++ b/include/linux/futex_types.h
@@ -7,14 +7,13 @@
 #include <linux/mutex_types.h>
 #include <linux/types.h>
 
-struct compat_robust_list_head;
 struct futex_pi_state;
 struct robust_list_head;
 
 /**
  * struct futex_sched_data - Futex related per task data
  * @robust_list:	User space registered robust list pointer
- * @compat_robust_list:	User space registered robust list pointer for compat tasks
+ * @robust_list32:	User space registered robust list pointer for compat tasks
  * @pi_state_list:	List head for Priority Inheritance (PI) state management
  * @pi_state_cache:	Pointer to cache one PI state object per task
  * @exit_mutex:		Mutex for serializing exit
@@ -23,7 +22,7 @@ struct robust_list_head;
 struct futex_sched_data {
 	struct robust_list_head __user		*robust_list;
 #ifdef CONFIG_COMPAT
-	struct compat_robust_list_head __user	*compat_robust_list;
+	struct robust_list_head32 __user *robust_list32;
 #endif
 	struct list_head			pi_state_list;
 	struct futex_pi_state			*pi_state_cache;
diff --git a/include/uapi/linux/futex.h b/include/uapi/linux/futex.h
index 10a36c551675..b39f8a23a84b 100644
--- a/include/uapi/linux/futex.h
+++ b/include/uapi/linux/futex.h
@@ -179,6 +179,16 @@ struct robust_list_head {
 	struct robust_list __user *list_op_pending;
 };
 
+struct robust_list32 {
+	__u32 next;
+};
+
+struct robust_list_head32 {
+	struct robust_list32	list;
+	__s32			futex_offset;
+	__u32			list_op_pending;
+};
+
 /*
  * Are there any waiters for this robust futex:
  */
diff --git a/kernel/futex/core.c b/kernel/futex/core.c
index a240638f69e5..28a6ad4a8da4 100644
--- a/kernel/futex/core.c
+++ b/kernel/futex/core.c
@@ -1243,9 +1243,10 @@ static void __user *futex_uaddr(struct robust_list __user *entry,
 /*
  * Fetch a robust-list pointer. Bit 0 signals PI futexes:
  */
-static inline int
-compat_fetch_robust_entry(compat_uptr_t *uentry, struct robust_list __user **entry,
-		   compat_uptr_t __user *head, unsigned int *pflags)
+static inline int fetch_robust_entry32(compat_uptr_t *uentry,
+				       struct robust_list __user **entry,
+				       compat_uptr_t __user *head,
+				       unsigned int *pflags)
 {
 	if (get_user(*uentry, head))
 		return -EFAULT;
@@ -1262,9 +1263,9 @@ compat_fetch_robust_entry(compat_uptr_t *uentry, struct robust_list __user **ent
  *
  * We silently return on any sign of list-walking problem.
  */
-static void compat_exit_robust_list(struct task_struct *curr)
+static void exit_robust_list32(struct task_struct *curr)
 {
-	struct compat_robust_list_head __user *head = current->futex.compat_robust_list;
+	struct robust_list_head32 __user *head = curr->futex.robust_list32;
 	unsigned int limit = ROBUST_LIST_LIMIT, cur_mod, next_mod, pend_mod;
 	struct robust_list __user *entry, *next_entry, *pending;
 	compat_uptr_t uentry, next_uentry, upending;
@@ -1275,7 +1276,7 @@ static void compat_exit_robust_list(struct task_struct *curr)
 	 * Fetch the list head (which was registered earlier, via
 	 * sys_set_robust_list()):
 	 */
-	if (compat_fetch_robust_entry(&uentry, &entry, &head->list.next, &cur_mod))
+	if (fetch_robust_entry32(&uentry, &entry, &head->list.next, &cur_mod))
 		return;
 	/*
 	 * Fetch the relative futex offset:
@@ -1286,7 +1287,7 @@ static void compat_exit_robust_list(struct task_struct *curr)
 	 * Fetch any possibly pending lock-add first, and handle it
 	 * if it exists:
 	 */
-	if (compat_fetch_robust_entry(&upending, &pending, &head->list_op_pending, &pend_mod))
+	if (fetch_robust_entry32(&upending, &pending, &head->list_op_pending, &pend_mod))
 		return;
 
 	next_entry = NULL;	/* avoid warning with gcc */
@@ -1295,7 +1296,7 @@ static void compat_exit_robust_list(struct task_struct *curr)
 		 * Fetch the next entry in the list before calling
 		 * handle_futex_death:
 		 */
-		rc = compat_fetch_robust_entry(&next_uentry, &next_entry,
+		rc = fetch_robust_entry32(&next_uentry, &next_entry,
 			(compat_uptr_t __user *)&entry->next, &next_mod);
 		/*
 		 * A pending lock might already be on the list, so
@@ -1327,20 +1328,20 @@ static void compat_exit_robust_list(struct task_struct *curr)
 	}
 }
 
-static bool compat_robust_list_clear_pending(u32 __user *pop)
+static bool robust_list_clear_pending32(u32 __user *pop)
 {
-	struct compat_robust_list_head __user *head = current->futex.compat_robust_list;
+	struct robust_list_head32 __user *head = current->futex.robust_list32;
 
 	if (!put_user(0U, pop))
 		return true;
 
 	/* See comment in robust_list_clear_pending(). */
 	if (pop == &head->list_op_pending)
-		current->futex.compat_robust_list = NULL;
+		current->futex.robust_list32 = NULL;
 	return false;
 }
 #else
-static bool compat_robust_list_clear_pending(u32 __user *pop_addr) { return false; }
+static bool robust_list_clear_pending32(u32 __user *pop_addr) { return false; }
 #endif
 
 #ifdef CONFIG_FUTEX_PI
@@ -1443,7 +1444,7 @@ bool futex_robust_list_clear_pending(void __user *pop, unsigned int flags)
 		return false;
 
 	if (IS_ENABLED(CONFIG_64BIT) && size32bit)
-		return compat_robust_list_clear_pending(pop);
+		return robust_list_clear_pending32(pop);
 
 	return robust_list_clear_pending(pop);
 }
@@ -1472,9 +1473,9 @@ static void futex_cleanup(struct task_struct *tsk)
 	}
 
 #ifdef CONFIG_COMPAT
-	if (unlikely(tsk->futex.compat_robust_list)) {
-		compat_exit_robust_list(tsk);
-		tsk->futex.compat_robust_list = NULL;
+	if (unlikely(tsk->futex.robust_list32)) {
+		exit_robust_list32(tsk);
+		tsk->futex.robust_list32 = NULL;
 	}
 #endif
 
diff --git a/kernel/futex/syscalls.c b/kernel/futex/syscalls.c
index 2fa19d9d008d..4a45bace75fc 100644
--- a/kernel/futex/syscalls.c
+++ b/kernel/futex/syscalls.c
@@ -39,7 +39,7 @@ static inline void __user *futex_task_robust_list(struct task_struct *p, bool co
 {
 #ifdef CONFIG_COMPAT
 	if (compat)
-		return p->futex.compat_robust_list;
+		return p->futex.robust_list32;
 #endif
 	return p->futex.robust_list;
 }
@@ -478,13 +478,14 @@ SYSCALL_DEFINE4(futex_requeue,
 }
 
 #ifdef CONFIG_COMPAT
-COMPAT_SYSCALL_DEFINE2(set_robust_list, struct compat_robust_list_head __user *, head,
+COMPAT_SYSCALL_DEFINE2(set_robust_list, struct robust_list_head32 __user *, head,
 		       compat_size_t, len)
 {
 	if (unlikely(len != sizeof(*head)))
 		return -EINVAL;
 
-	current->futex.compat_robust_list = head;
+	current->futex.robust_list32 = head;
+
 	return 0;
 }
 
@@ -492,7 +493,7 @@ COMPAT_SYSCALL_DEFINE3(get_robust_list, int, pid,
 			compat_uptr_t __user *, head_ptr,
 			compat_size_t __user *, len_ptr)
 {
-	struct compat_robust_list_head __user *head = futex_get_robust_list_common(pid, true);
+	struct robust_list_head32 __user *head = futex_get_robust_list_common(pid, true);
 
 	if (IS_ERR(head))
 		return PTR_ERR(head);

-- 
2.56.1


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

* [PATCH v8 03/10] futex: Make exit_robust_list32() unconditionally available for 64-bit kernels
  2026-11-15 17:31 [PATCH v8 00/10] futex: Create {set,get}_robust_list2() syscalls André Almeida
  2026-11-15 17:31 ` [PATCH v8 01/10] futex: Skip test_futex_robust_unlock() if not supported André Almeida
  2026-11-15 17:31 ` [PATCH v8 02/10] futex: Use explicit sizes for compat_robust_list structs André Almeida
@ 2026-11-15 17:31 ` André Almeida
  2026-11-15 17:31 ` [PATCH v8 04/10] futex: Create set_robust_list2() syscall André Almeida
                   ` (6 subsequent siblings)
  9 siblings, 0 replies; 14+ messages in thread
From: André Almeida @ 2026-11-15 17:31 UTC (permalink / raw)
  To: Ingo Molnar, Peter Zijlstra, Darren Hart, Davidlohr Bueso,
	Arnd Bergmann, Sebastian Andrzej Siewior, Waiman Long,
	Ryan Houdek, Thomas Gleixner
  Cc: linux-kernel, linux-kselftest, linux-api, kernel-dev, André Almeida

The new syscall set_robust_list2() needs to handle both 64-bit and
32-bit robust lists, but not every 64-bit platform have compat entry
points. Make exit_robust_list32() unconditionally available for 64-bit
kernels regardless of having a compat configuration.

Signed-off-by: André Almeida <andrealmeid@igalia.com>
---
 kernel/futex/core.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/kernel/futex/core.c b/kernel/futex/core.c
index 28a6ad4a8da4..6fce97012015 100644
--- a/kernel/futex/core.c
+++ b/kernel/futex/core.c
@@ -1230,12 +1230,12 @@ static bool robust_list_clear_pending(unsigned long __user *pop)
 	return false;
 }
 
-#ifdef CONFIG_COMPAT
+#ifdef CONFIG_64BIT
 static void __user *futex_uaddr(struct robust_list __user *entry,
 				compat_long_t futex_offset)
 {
-	compat_uptr_t base = ptr_to_compat(entry);
-	void __user *uaddr = compat_ptr(base + futex_offset);
+	u32 base = (u32)(unsigned long)(entry);
+	void __user *uaddr = (void __user *)(unsigned long)(base + futex_offset);
 
 	return uaddr;
 }
@@ -1268,8 +1268,8 @@ static void exit_robust_list32(struct task_struct *curr)
 	struct robust_list_head32 __user *head = curr->futex.robust_list32;
 	unsigned int limit = ROBUST_LIST_LIMIT, cur_mod, next_mod, pend_mod;
 	struct robust_list __user *entry, *next_entry, *pending;
-	compat_uptr_t uentry, next_uentry, upending;
-	compat_long_t futex_offset;
+	u32 uentry, next_uentry, upending;
+	s32 futex_offset;
 	int rc;
 
 	/*
@@ -1472,7 +1472,7 @@ static void futex_cleanup(struct task_struct *tsk)
 		tsk->futex.robust_list = NULL;
 	}
 
-#ifdef CONFIG_COMPAT
+#ifdef CONFIG_64BIT
 	if (unlikely(tsk->futex.robust_list32)) {
 		exit_robust_list32(tsk);
 		tsk->futex.robust_list32 = NULL;

-- 
2.56.1


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

* [PATCH v8 04/10] futex: Create set_robust_list2() syscall
  2026-11-15 17:31 [PATCH v8 00/10] futex: Create {set,get}_robust_list2() syscalls André Almeida
                   ` (2 preceding siblings ...)
  2026-11-15 17:31 ` [PATCH v8 03/10] futex: Make exit_robust_list32() unconditionally available for 64-bit kernels André Almeida
@ 2026-11-15 17:31 ` André Almeida
  2026-11-15 17:31 ` [PATCH v8 05/10] futex: Create get_robust_list2() syscall André Almeida
                   ` (5 subsequent siblings)
  9 siblings, 0 replies; 14+ messages in thread
From: André Almeida @ 2026-11-15 17:31 UTC (permalink / raw)
  To: Ingo Molnar, Peter Zijlstra, Darren Hart, Davidlohr Bueso,
	Arnd Bergmann, Sebastian Andrzej Siewior, Waiman Long,
	Ryan Houdek, Thomas Gleixner
  Cc: linux-kernel, linux-kselftest, linux-api, kernel-dev, André Almeida

Emulators (like FEX-Emu, to run x86 apps on top of Aarch64) have two
special needs about robust lists: to be able to register more than one
robust list, one of the app being emulated and one list for the emulator
itself; and to be able to walk on 32-bit robusts lists on a 64-bit
platform without compat entry points.

The current syscall allows for one robust list per task (on x86-64, it
can have two if compat is enabled) and on Aarch64 there's no way to
parse a 32-bit robust list. The current syscall cannot be expanded to
solve both needs, so create a new syscall, set_robust_list2() with the
following signature:

  sys_set_robust_list2(struct robust_list_head *head, unsigned int cmd,
		       unsigned int flags)

The new syscall allows to set multiple lists per task, of 64-bit or
32-bit types.

 - `*head` is the same structure used in the current syscall.
 - `cmd` defines the operation to perform:
   - `FUTEX_ROBUST_LIST_CMD_CREATE_{32, 64}` sets a new robust list head,
   the kernel returns the index of the list. User can choose between 32 or
   64 bit for pointer size of the list head.
   - FUTEX_ROBUST_LIST_CMD_MODIFY_{32, 64}` change the `*head` value of a
   list. Setting it to NULL destroys an index and let it free to be
   allocated by other CREATE caller.
   - `FUTEX_ROBUST_LIST_CMD_LIST_LIMIT` gets the limit of lists per task
 - `flag` is unused now but can be used to expand the interface

The array of lists is dynamically allocated in the first use, but has a
fixed size determined by the kernel. 8 slots are more than enough to
cover the target use case and allows for more use cases. The command for
getting the list limit allows to userspace check if the kernel ever
expands this list. The first two slots are reserved for the kernel, to
store the original syscall robust_list_head's.

The array of lists is destroyed only during task exit.

The `FUTEX_ROBUST_LIST_CMD_CREATE_64` operation is only available for
64-bit kernels. In such kernels, lists created with
`FUTEX_ROBUST_LIST_CMD_SET_32` are marked with
`FUTEX_ROBUST_LIST_ENTRY_32BIT` and the kernel handles it with a special
function exit_robust_list32() to be able to walk in a list of 32-bit
pointers.

For 32-bit kernels, there's no special function available as every user
list and list handling functions will all have the same bitness.

Signed-off-by: André Almeida <andrealmeid@igalia.com>
---
 include/linux/futex.h       |  24 ++++++++
 include/linux/futex_types.h |   2 +
 include/uapi/linux/futex.h  |  18 ++++++
 kernel/futex/core.c         | 138 +++++++++++++++++++++++++++++++++++++++++---
 kernel/futex/futex.h        |   5 ++
 kernel/futex/syscalls.c     |  55 ++++++++++++++++++
 kernel/sys_ni.c             |   1 +
 7 files changed, 236 insertions(+), 7 deletions(-)

diff --git a/include/linux/futex.h b/include/linux/futex.h
index 93316876a4ee..03a3973a7068 100644
--- a/include/linux/futex.h
+++ b/include/linux/futex.h
@@ -5,6 +5,7 @@
 #include <linux/sched.h>
 #include <linux/ktime.h>
 #include <linux/mm_types.h>
+#include <linux/compat.h>
 
 #include <uapi/linux/futex.h>
 
@@ -66,6 +67,28 @@ enum {
 	FUTEX_STATE_DEAD,
 };
 
+#define FUTEX_ROBUST_LIST_NATIVE_IDX	0
+#define FUTEX_ROBUST_LIST_COMPAT_IDX	1
+#define FUTEX_ROBUST_LIST2_IDX		2
+#define FUTEX_ROBUST_LISTS_PER_USER	8
+#define FUTEX_ROBUST_LIST2_MAX_IDX	(FUTEX_ROBUST_LIST2_IDX + FUTEX_ROBUST_LISTS_PER_USER)
+
+/*
+ * List entries without _32BIT flag are using the native machine size
+ */
+#define FUTEX_ROBUST_LIST_ENTRY_INUSE	0x1UL
+#define FUTEX_ROBUST_LIST_ENTRY_32BIT	0x2UL
+#define FUTEX_ROBUST_LIST_ENTRY_MASK	(~0x3UL)
+
+static inline bool futex_in_32bit_syscall(void)
+{
+#ifdef CONFIG_X86
+	return !IS_ENABLED(CONFIG_64BIT) || in_32bit_syscall();
+#else
+	return !IS_ENABLED(CONFIG_64BIT);
+#endif
+}
+
 static inline void futex_init_task(struct task_struct *tsk)
 {
 	memset(&tsk->futex, 0, sizeof(tsk->futex));
@@ -76,6 +99,7 @@ static inline void futex_init_task(struct task_struct *tsk)
 #ifdef CONFIG_COMPAT
 	tsk->futex.robust_list32 = NULL;
 #endif
+	tsk->futex.robust_lists = NULL;
 }
 
 void futex_exit_recursive(struct task_struct *tsk);
diff --git a/include/linux/futex_types.h b/include/linux/futex_types.h
index f58616d7e20b..58321314ecab 100644
--- a/include/linux/futex_types.h
+++ b/include/linux/futex_types.h
@@ -18,6 +18,7 @@ struct robust_list_head;
  * @pi_state_cache:	Pointer to cache one PI state object per task
  * @exit_mutex:		Mutex for serializing exit
  * @state:		Futex handling state to handle exit races correctly
+ * @robust_lists:	List of robust lists heads
  */
 struct futex_sched_data {
 	struct robust_list_head __user		*robust_list;
@@ -28,6 +29,7 @@ struct futex_sched_data {
 	struct futex_pi_state			*pi_state_cache;
 	struct mutex				exit_mutex;
 	unsigned int				state;
+	uintptr_t				*robust_lists;
 };
 
 #ifdef CONFIG_FUTEX_PRIVATE_HASH
diff --git a/include/uapi/linux/futex.h b/include/uapi/linux/futex.h
index b39f8a23a84b..becf43230df4 100644
--- a/include/uapi/linux/futex.h
+++ b/include/uapi/linux/futex.h
@@ -189,6 +189,24 @@ struct robust_list_head32 {
 	__u32			list_op_pending;
 };
 
+/*
+ * Commands for set_robust_list2 syscall
+ */
+enum robust_list2_cmd {
+	FUTEX_ROBUST_LIST_CMD_CREATE_64,
+	FUTEX_ROBUST_LIST_CMD_CREATE_32,
+	FUTEX_ROBUST_LIST_CMD_MODIFY_64,
+	FUTEX_ROBUST_LIST_CMD_MODIFY_32,
+	FUTEX_ROBUST_LIST_CMD_LIST_LIMIT,
+	FUTEX_ROBUST_LIST_CMD_USER_MAX,
+
+	/*
+	 * Kernel internal, rejected for user space
+	 */
+	FUTEX_ROBUST_LIST_SET_NATIVE = 128,
+	FUTEX_ROBUST_LIST_SET_COMPAT,
+};
+
 /*
  * Are there any waiters for this robust futex:
  */
diff --git a/kernel/futex/core.c b/kernel/futex/core.c
index 6fce97012015..dd6fa8035fb6 100644
--- a/kernel/futex/core.c
+++ b/kernel/futex/core.c
@@ -73,6 +73,90 @@ struct futex_private_hash {
 	struct futex_hash_bucket queues[];
 };
 
+int futex_robust_list_create(uintptr_t head, enum robust_list2_cmd cmd)
+{
+	uintptr_t *rl = current->futex.robust_lists, entry = FUTEX_ROBUST_LIST_ENTRY_INUSE;
+	unsigned int index;
+
+	if (!rl) {
+		rl = kcalloc(FUTEX_ROBUST_LIST2_MAX_IDX, sizeof(*rl), GFP_KERNEL);
+		if (!rl)
+			return -ENOMEM;
+
+		scoped_guard(mutex, &current->futex.exit_mutex) {
+			/* check if another thread set the list before us */
+			if (current->futex.robust_lists) {
+				kfree(rl);
+				rl = current->futex.robust_lists;
+			} else {
+				current->futex.robust_lists = rl;
+			}
+		}
+
+	}
+
+	switch (cmd) {
+	case FUTEX_ROBUST_LIST_CMD_CREATE_32:
+		if (head)
+			entry |= FUTEX_ROBUST_LIST_ENTRY_32BIT;
+		fallthrough;
+	case FUTEX_ROBUST_LIST_CMD_CREATE_64:
+		/* Search for an empty slot */
+		for (index = FUTEX_ROBUST_LIST2_IDX;
+		     index < FUTEX_ROBUST_LIST2_MAX_IDX; index++) {
+			if (rl[index] == 0)
+				goto exit;
+		}
+		return -ENOSPC;
+	default:
+		return -EINVAL;
+	}
+
+exit:
+	entry |= head;
+	scoped_guard(mutex, &current->futex.exit_mutex)
+		rl[index] = entry;
+
+	return index;
+}
+
+int futex_robust_list_modify(uintptr_t head, enum robust_list2_cmd cmd,
+			     unsigned int index)
+{
+	uintptr_t *rl = current->futex.robust_lists, entry = head;
+
+	if (index >= FUTEX_ROBUST_LIST2_MAX_IDX - FUTEX_ROBUST_LIST2_IDX)
+		return -EINVAL;
+
+	/* See comment about index mapping at sys_set_robust_list2() */
+	index += FUTEX_ROBUST_LIST2_IDX;
+
+	if (!rl || !rl[index])
+		return -ENOENT;
+
+	switch (cmd) {
+	case FUTEX_ROBUST_LIST_CMD_MODIFY_64:
+		if (rl[index] & FUTEX_ROBUST_LIST_ENTRY_32BIT)
+			return -EINVAL;
+		if (futex_in_32bit_syscall())
+			return -EINVAL;
+		break;
+	case FUTEX_ROBUST_LIST_CMD_MODIFY_32:
+		if (!(rl[index]  & FUTEX_ROBUST_LIST_ENTRY_32BIT))
+			return -EINVAL;
+		if (entry)
+			entry |= FUTEX_ROBUST_LIST_ENTRY_32BIT;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	scoped_guard(mutex, &current->futex.exit_mutex)
+		rl[index] = entry;
+
+	return 0;
+}
+
 /*
  * Fault injections for futexes.
  */
@@ -1148,9 +1232,8 @@ static inline int fetch_robust_entry(struct robust_list __user **entry,
  *
  * We silently return on any sign of list-walking problem.
  */
-static void exit_robust_list(struct task_struct *curr)
+static void exit_robust_list(struct task_struct *curr, struct robust_list_head __user *head)
 {
-	struct robust_list_head __user *head = curr->futex.robust_list;
 	unsigned int limit = ROBUST_LIST_LIMIT, cur_mod, next_mod, pend_mod;
 	struct robust_list __user *entry, *next_entry, *pending;
 	unsigned long futex_offset;
@@ -1263,9 +1346,8 @@ static inline int fetch_robust_entry32(compat_uptr_t *uentry,
  *
  * We silently return on any sign of list-walking problem.
  */
-static void exit_robust_list32(struct task_struct *curr)
+static void exit_robust_list32(struct task_struct *curr, struct robust_list_head32 __user *head)
 {
-	struct robust_list_head32 __user *head = curr->futex.robust_list32;
 	unsigned int limit = ROBUST_LIST_LIMIT, cur_mod, next_mod, pend_mod;
 	struct robust_list __user *entry, *next_entry, *pending;
 	u32 uentry, next_uentry, upending;
@@ -1342,7 +1424,12 @@ static bool robust_list_clear_pending32(u32 __user *pop)
 }
 #else
 static bool robust_list_clear_pending32(u32 __user *pop_addr) { return false; }
-#endif
+
+static void exit_robust_list32(struct task_struct *curr, struct robust_list_head32 __user *head)
+{
+	pr_crit("32-bit kernel should never call %s", __func__);
+}
+#endif /* CONFIG_64BIT */
 
 #ifdef CONFIG_FUTEX_PI
 
@@ -1465,16 +1552,53 @@ void __futex_fixup_robust_unlock(struct pt_regs *regs, struct futex_unlock_cs_ra
 }
 #endif /* CONFIG_FUTEX_ROBUST_UNLOCK */
 
+static void exit_robust_lists(struct task_struct *tsk)
+{
+	uintptr_t *rl = tsk->futex.robust_lists;
+
+	tsk->futex.robust_lists = NULL;
+
+	for (unsigned int idx = 0; idx < FUTEX_ROBUST_LIST2_MAX_IDX; idx++) {
+		uintptr_t entry = rl[idx];
+
+		if (!(entry & FUTEX_ROBUST_LIST_ENTRY_MASK))
+			continue;
+
+		/*
+		 * If the list type is the same as the kernel bitness, always
+		 * calls exit_robust_list(). exit_robust_list32() is only for
+		 * 32-bit lists in a 64-bit kernel.
+		 */
+		if (IS_ENABLED(CONFIG_64BIT) && (entry & FUTEX_ROBUST_LIST_ENTRY_32BIT)) {
+			struct robust_list_head32 __user *head;
+
+			entry &= FUTEX_ROBUST_LIST_ENTRY_MASK;
+
+			head = (__force struct robust_list_head32 __user *)entry;
+			exit_robust_list32(tsk, head);
+		} else {
+			struct robust_list_head __user *head;
+
+			entry &= FUTEX_ROBUST_LIST_ENTRY_MASK;
+
+			head = (__force struct robust_list_head __user *)entry;
+			exit_robust_list(tsk, head);
+		}
+	}
+
+	kfree(rl);
+}
+
 static void futex_cleanup(struct task_struct *tsk)
 {
 	if (unlikely(tsk->futex.robust_list)) {
-		exit_robust_list(tsk);
+		exit_robust_list(tsk, tsk->futex.robust_list);
 		tsk->futex.robust_list = NULL;
 	}
 
 #ifdef CONFIG_64BIT
 	if (unlikely(tsk->futex.robust_list32)) {
-		exit_robust_list32(tsk);
+		exit_robust_list32(tsk, tsk->futex.robust_list32);
 		tsk->futex.robust_list32 = NULL;
 	}
 #endif
diff --git a/kernel/futex/futex.h b/kernel/futex/futex.h
index f00f0863ed44..7706d2b6f8a9 100644
--- a/kernel/futex/futex.h
+++ b/kernel/futex/futex.h
@@ -478,4 +478,9 @@ extern int futex_lock_pi(u32 __user *uaddr, unsigned int flags, ktime_t *time, i
 
 bool futex_robust_list_clear_pending(void __user *pop, unsigned int flags);
 
+int futex_robust_list_create(uintptr_t head, enum robust_list2_cmd cmd);
+
+int futex_robust_list_modify(uintptr_t head, enum robust_list2_cmd cmd, unsigned
+			     int index);
+
 #endif /* _FUTEX_H */
diff --git a/kernel/futex/syscalls.c b/kernel/futex/syscalls.c
index 4a45bace75fc..48e87b5e4e33 100644
--- a/kernel/futex/syscalls.c
+++ b/kernel/futex/syscalls.c
@@ -105,6 +105,61 @@ SYSCALL_DEFINE3(get_robust_list, int, pid,
 	return put_user(head, head_ptr);
 }
 
+SYSCALL_DEFINE4(set_robust_list2, struct robust_list_head * __user, head, unsigned int,
+		cmd, unsigned int, index, unsigned int, flags)
+{
+	uintptr_t entry = (__force uintptr_t)head;
+	size_t align = sizeof(u32);
+	int ret;
+
+	if (flags)
+		return -EINVAL;
+
+	if (cmd >= FUTEX_ROBUST_LIST_CMD_USER_MAX)
+		return -EINVAL;
+
+	if (cmd == FUTEX_ROBUST_LIST_CMD_CREATE_64 ||
+	    cmd == FUTEX_ROBUST_LIST_CMD_MODIFY_64) {
+		if (futex_in_32bit_syscall())
+			return -EOPNOTSUPP;
+		align = sizeof(u64);
+	}
+
+	switch (cmd) {
+	case FUTEX_ROBUST_LIST_CMD_CREATE_64:
+	case FUTEX_ROBUST_LIST_CMD_CREATE_32:
+		if (index)
+			return -EINVAL;
+
+		if (entry % align)
+			return -EINVAL;
+
+		/*
+		 * The first two indexes are reserved for the kernel to be used
+		 * with the legacy syscall, so we hide them from userspace.
+		 *
+		 * We map [0, FUTEX_ROBUST_LISTS_PER_USER) to
+		 *  [FUTEX_ROBUST_LIST2_IDX, FUTEX_ROBUST_LIST2_MAX_IDX)
+		 */
+		ret = futex_robust_list_create(entry, cmd);
+
+		if (ret >= 0)
+			ret -= FUTEX_ROBUST_LIST2_IDX;
+
+		return ret;
+
+	case FUTEX_ROBUST_LIST_CMD_MODIFY_64:
+	case FUTEX_ROBUST_LIST_CMD_MODIFY_32:
+		if (entry % align)
+			return -EINVAL;
+		return futex_robust_list_modify(entry, cmd, index);
+	case FUTEX_ROBUST_LIST_CMD_LIST_LIMIT:
+		return FUTEX_ROBUST_LISTS_PER_USER;
+	}
+
+	return -EINVAL;
+}
+
 long do_futex(u32 __user *uaddr, int op, u32 val, ktime_t *timeout,
 		u32 __user *uaddr2, u32 val2, u32 val3)
 {
diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c
index c8be0abaa407..0bb92b3cb589 100644
--- a/kernel/sys_ni.c
+++ b/kernel/sys_ni.c
@@ -172,6 +172,7 @@ COND_SYSCALL_COMPAT(fadvise64_64);
 COND_SYSCALL(lsm_get_self_attr);
 COND_SYSCALL(lsm_set_self_attr);
 COND_SYSCALL(lsm_list_modules);
+COND_SYSCALL(set_robust_list2);
 
 /* CONFIG_MMU only */
 COND_SYSCALL(swapon);

-- 
2.56.1


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

* [PATCH v8 05/10] futex: Create get_robust_list2() syscall
  2026-11-15 17:31 [PATCH v8 00/10] futex: Create {set,get}_robust_list2() syscalls André Almeida
                   ` (3 preceding siblings ...)
  2026-11-15 17:31 ` [PATCH v8 04/10] futex: Create set_robust_list2() syscall André Almeida
@ 2026-11-15 17:31 ` André Almeida
  2026-11-15 17:31 ` [PATCH v8 06/10] futex: Wire up set_robust_list2 syscall André Almeida
                   ` (4 subsequent siblings)
  9 siblings, 0 replies; 14+ messages in thread
From: André Almeida @ 2026-11-15 17:31 UTC (permalink / raw)
  To: Ingo Molnar, Peter Zijlstra, Darren Hart, Davidlohr Bueso,
	Arnd Bergmann, Sebastian Andrzej Siewior, Waiman Long,
	Ryan Houdek, Thomas Gleixner
  Cc: linux-kernel, linux-kselftest, linux-api, kernel-dev, André Almeida

As in the original robust list interface, to pair with
set_robust_list2(), create a get_robust_list2() syscall with the
following signature:

  get_robust_list2(int pid, void __user **head_ptr, unsigned int index,
		   unsigned int flags)

  - `pid` sets with task's list should be returned. If is 0, it gets the
    list of the calling task.
  - `index` is the index of the list to get
  - `flags` is unused but can be used for expanding the interface

Signed-off-by: André Almeida <andrealmeid@igalia.com>
---
 kernel/futex/syscalls.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++---
 kernel/sys_ni.c         |  1 +
 2 files changed, 63 insertions(+), 4 deletions(-)

diff --git a/kernel/futex/syscalls.c b/kernel/futex/syscalls.c
index 48e87b5e4e33..0ecb32afd5e1 100644
--- a/kernel/futex/syscalls.c
+++ b/kernel/futex/syscalls.c
@@ -44,7 +44,7 @@ static inline void __user *futex_task_robust_list(struct task_struct *p, bool co
 	return p->futex.robust_list;
 }
 
-static void __user *futex_get_robust_list_common(int pid, bool compat)
+static void __user *futex_get_robust_list_common(int pid, bool compat, int index)
 {
 	struct task_struct *p = current;
 	void __user *head;
@@ -71,7 +71,15 @@ static void __user *futex_get_robust_list_common(int pid, bool compat)
 	if (!ptrace_may_access(p, PTRACE_MODE_READ_REALCREDS))
 		goto err_unlock;
 
-	head = futex_task_robust_list(p, compat);
+	if (index >= 0) {
+		scoped_guard(mutex, &p->futex.exit_mutex) {
+			uintptr_t *rl = p->futex.robust_lists;
+
+			head = rl ? (void __user *) rl[index] : NULL;
+		}
+	} else {
+		head = futex_task_robust_list(p, compat);
+	}
 
 	up_read(&p->signal->exec_update_lock);
 	put_task_struct(p);
@@ -95,7 +103,7 @@ SYSCALL_DEFINE3(get_robust_list, int, pid,
 		struct robust_list_head __user * __user *, head_ptr,
 		size_t __user *, len_ptr)
 {
-	struct robust_list_head __user *head = futex_get_robust_list_common(pid, false);
+	struct robust_list_head __user *head = futex_get_robust_list_common(pid, false, -1);
 
 	if (IS_ERR(head))
 		return PTR_ERR(head);
@@ -160,6 +168,56 @@ SYSCALL_DEFINE4(set_robust_list2, struct robust_list_head * __user, head, unsign
 	return -EINVAL;
 }
 
+SYSCALL_DEFINE4(get_robust_list2, int, pid,
+		void __user * __user *, head_ptr,
+		unsigned int, index, unsigned int, flags)
+{
+	struct robust_list_head *head;
+	void __user *entry_ptr;
+	uintptr_t entry;
+
+	if (index >= FUTEX_ROBUST_LISTS_PER_USER)
+		return -EINVAL;
+
+	if (flags)
+		return -EINVAL;
+
+	/*
+	 * The first two indexes are reserved for the kernel to be used with the
+	 * legacy syscall, so we hide them from userspace.
+	 *
+	 * We map [0, FUTEX_ROBUST_LISTS_PER_USER) to
+	 *  [FUTEX_ROBUST_LIST2_IDX, FUTEX_ROBUST_LIST2_MAX_IDX)
+	 */
+	index += FUTEX_ROBUST_LIST2_IDX;
+
+	entry_ptr = futex_get_robust_list_common(pid, false, index);
+	if (IS_ERR(entry_ptr))
+		return PTR_ERR(entry_ptr);
+
+	entry = (uintptr_t) entry_ptr;
+
+	if (futex_in_32bit_syscall()) {
+		u32 entry32;
+
+		if (entry && !(entry & FUTEX_ROBUST_LIST_ENTRY_32BIT))
+			return -EOPNOTSUPP;
+
+		entry32 = (u32)entry;
+		entry32 &= FUTEX_ROBUST_LIST_ENTRY_MASK;
+
+		if (copy_to_user(head_ptr, &entry32, sizeof(entry32)))
+			return -EFAULT;
+
+		return 0;
+	}
+
+	entry &= FUTEX_ROBUST_LIST_ENTRY_MASK;
+	head = (__force struct robust_list_head __user *)entry;
+
+	return put_user(head, head_ptr);
+}
+
 long do_futex(u32 __user *uaddr, int op, u32 val, ktime_t *timeout,
 		u32 __user *uaddr2, u32 val2, u32 val3)
 {
@@ -548,7 +606,7 @@ COMPAT_SYSCALL_DEFINE3(get_robust_list, int, pid,
 			compat_uptr_t __user *, head_ptr,
 			compat_size_t __user *, len_ptr)
 {
-	struct robust_list_head32 __user *head = futex_get_robust_list_common(pid, true);
+	struct robust_list_head32 __user *head = futex_get_robust_list_common(pid, true, -1);
 
 	if (IS_ERR(head))
 		return PTR_ERR(head);
diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c
index 0bb92b3cb589..d8bbcd87d535 100644
--- a/kernel/sys_ni.c
+++ b/kernel/sys_ni.c
@@ -173,6 +173,7 @@ COND_SYSCALL(lsm_get_self_attr);
 COND_SYSCALL(lsm_set_self_attr);
 COND_SYSCALL(lsm_list_modules);
 COND_SYSCALL(set_robust_list2);
+COND_SYSCALL(get_robust_list2);
 
 /* CONFIG_MMU only */
 COND_SYSCALL(swapon);

-- 
2.56.1


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

* [PATCH v8 06/10] futex: Wire up set_robust_list2 syscall
  2026-11-15 17:31 [PATCH v8 00/10] futex: Create {set,get}_robust_list2() syscalls André Almeida
                   ` (4 preceding siblings ...)
  2026-11-15 17:31 ` [PATCH v8 05/10] futex: Create get_robust_list2() syscall André Almeida
@ 2026-11-15 17:31 ` André Almeida
  2026-11-15 20:55   ` kernel test robot
  2026-11-15 21:30   ` kernel test robot
  2026-11-15 17:31 ` [PATCH v8 07/10] futex: Wire up get_robust_list2 syscall André Almeida
                   ` (3 subsequent siblings)
  9 siblings, 2 replies; 14+ messages in thread
From: André Almeida @ 2026-11-15 17:31 UTC (permalink / raw)
  To: Ingo Molnar, Peter Zijlstra, Darren Hart, Davidlohr Bueso,
	Arnd Bergmann, Sebastian Andrzej Siewior, Waiman Long,
	Ryan Houdek, Thomas Gleixner
  Cc: linux-kernel, linux-kselftest, linux-api, kernel-dev, André Almeida

Wire up the new set_robust_list2 syscall in all available architectures.

Signed-off-by: André Almeida <andrealmeid@igalia.com>
---
 arch/alpha/kernel/syscalls/syscall.tbl      | 1 +
 arch/arm/tools/syscall.tbl                  | 1 +
 arch/m68k/kernel/syscalls/syscall.tbl       | 1 +
 arch/microblaze/kernel/syscalls/syscall.tbl | 1 +
 arch/mips/kernel/syscalls/syscall_n32.tbl   | 1 +
 arch/mips/kernel/syscalls/syscall_n64.tbl   | 1 +
 arch/mips/kernel/syscalls/syscall_o32.tbl   | 1 +
 arch/parisc/kernel/syscalls/syscall.tbl     | 1 +
 arch/powerpc/kernel/syscalls/syscall.tbl    | 1 +
 arch/s390/kernel/syscalls/syscall.tbl       | 1 +
 arch/sh/kernel/syscalls/syscall.tbl         | 1 +
 arch/sparc/kernel/syscalls/syscall.tbl      | 1 +
 arch/x86/entry/syscalls/syscall_32.tbl      | 1 +
 arch/x86/entry/syscalls/syscall_64.tbl      | 1 +
 arch/xtensa/kernel/syscalls/syscall.tbl     | 1 +
 include/uapi/asm-generic/unistd.h           | 5 ++++-
 scripts/syscall.tbl                         | 1 +
 17 files changed, 20 insertions(+), 1 deletion(-)

diff --git a/arch/alpha/kernel/syscalls/syscall.tbl b/arch/alpha/kernel/syscalls/syscall.tbl
index 52e3538cc7df..cdf641845014 100644
--- a/arch/alpha/kernel/syscalls/syscall.tbl
+++ b/arch/alpha/kernel/syscalls/syscall.tbl
@@ -512,3 +512,4 @@
 580	common	listns				sys_listns
 581	common	rseq_slice_yield		sys_rseq_slice_yield
 582	common	fchroot				sys_fchroot
+583	common	set_robust_list2		sys_set_robust_list2
diff --git a/arch/arm/tools/syscall.tbl b/arch/arm/tools/syscall.tbl
index 55717ed32c27..c287461803ff 100644
--- a/arch/arm/tools/syscall.tbl
+++ b/arch/arm/tools/syscall.tbl
@@ -487,3 +487,4 @@
 470	common	listns				sys_listns
 471	common	rseq_slice_yield		sys_rseq_slice_yield
 472	common	fchroot				sys_fchroot
+473	common	set_robust_list2		sys_set_robust_list2
diff --git a/arch/m68k/kernel/syscalls/syscall.tbl b/arch/m68k/kernel/syscalls/syscall.tbl
index ba7a4d8903d0..beb0ba7f350c 100644
--- a/arch/m68k/kernel/syscalls/syscall.tbl
+++ b/arch/m68k/kernel/syscalls/syscall.tbl
@@ -472,3 +472,4 @@
 470	common	listns				sys_listns
 471	common	rseq_slice_yield		sys_rseq_slice_yield
 472	common	fchroot				sys_fchroot
+473	common  set_robust_list2		sys_set_robust_list2
diff --git a/arch/microblaze/kernel/syscalls/syscall.tbl b/arch/microblaze/kernel/syscalls/syscall.tbl
index 76d7cbe2a133..bf04133f7239 100644
--- a/arch/microblaze/kernel/syscalls/syscall.tbl
+++ b/arch/microblaze/kernel/syscalls/syscall.tbl
@@ -478,3 +478,4 @@
 470	common	listns				sys_listns
 471	common	rseq_slice_yield		sys_rseq_slice_yield
 472	common	fchroot				sys_fchroot
+473	common	set_robust_list2		sys_set_robust_list2
diff --git a/arch/mips/kernel/syscalls/syscall_n32.tbl b/arch/mips/kernel/syscalls/syscall_n32.tbl
index 9ae88e4eac61..5b5b217ee7f3 100644
--- a/arch/mips/kernel/syscalls/syscall_n32.tbl
+++ b/arch/mips/kernel/syscalls/syscall_n32.tbl
@@ -411,3 +411,4 @@
 470	n32	listns				sys_listns
 471	n32	rseq_slice_yield		sys_rseq_slice_yield
 472	n32	fchroot				sys_fchroot
+473	n32	set_robust_list2		sys_set_robust_list2
diff --git a/arch/mips/kernel/syscalls/syscall_n64.tbl b/arch/mips/kernel/syscalls/syscall_n64.tbl
index 83dc93a0712f..6f203cb3a558 100644
--- a/arch/mips/kernel/syscalls/syscall_n64.tbl
+++ b/arch/mips/kernel/syscalls/syscall_n64.tbl
@@ -387,3 +387,4 @@
 470	n64	listns				sys_listns
 471	n64	rseq_slice_yield		sys_rseq_slice_yield
 472	n64	fchroot				sys_fchroot
+473	n64	set_robust_list2		sys_set_robust_list2
diff --git a/arch/mips/kernel/syscalls/syscall_o32.tbl b/arch/mips/kernel/syscalls/syscall_o32.tbl
index 9c62429c9b7b..d170650521a7 100644
--- a/arch/mips/kernel/syscalls/syscall_o32.tbl
+++ b/arch/mips/kernel/syscalls/syscall_o32.tbl
@@ -460,3 +460,4 @@
 470	o32	listns				sys_listns
 471	o32	rseq_slice_yield		sys_rseq_slice_yield
 472	o32	fchroot				sys_fchroot
+473	o32	set_robust_list2		sys_set_robust_list2
diff --git a/arch/parisc/kernel/syscalls/syscall.tbl b/arch/parisc/kernel/syscalls/syscall.tbl
index 88adc4016cce..f9317ff28e37 100644
--- a/arch/parisc/kernel/syscalls/syscall.tbl
+++ b/arch/parisc/kernel/syscalls/syscall.tbl
@@ -471,3 +471,4 @@
 470	common	listns				sys_listns
 471	common	rseq_slice_yield		sys_rseq_slice_yield
 472	common	fchroot				sys_fchroot
+473	common	set_robust_list2		sys_set_robust_list2
diff --git a/arch/powerpc/kernel/syscalls/syscall.tbl b/arch/powerpc/kernel/syscalls/syscall.tbl
index cfbb70039ff0..acb9d446d1f6 100644
--- a/arch/powerpc/kernel/syscalls/syscall.tbl
+++ b/arch/powerpc/kernel/syscalls/syscall.tbl
@@ -563,3 +563,4 @@
 470	common	listns				sys_listns
 471	nospu	rseq_slice_yield		sys_rseq_slice_yield
 472	common	fchroot				sys_fchroot
+473	common	set_robust_list2		sys_set_robust_list2
diff --git a/arch/s390/kernel/syscalls/syscall.tbl b/arch/s390/kernel/syscalls/syscall.tbl
index 1b45e68a217b..987e026ffbcf 100644
--- a/arch/s390/kernel/syscalls/syscall.tbl
+++ b/arch/s390/kernel/syscalls/syscall.tbl
@@ -399,3 +399,4 @@
 470	common	listns				sys_listns
 471	common	rseq_slice_yield		sys_rseq_slice_yield
 472	common	fchroot				sys_fchroot
+473	common	set_robust_list2		sys_set_robust_list2
diff --git a/arch/sh/kernel/syscalls/syscall.tbl b/arch/sh/kernel/syscalls/syscall.tbl
index ace068dff0de..c944333c1990 100644
--- a/arch/sh/kernel/syscalls/syscall.tbl
+++ b/arch/sh/kernel/syscalls/syscall.tbl
@@ -476,3 +476,4 @@
 470	common	listns				sys_listns
 471	common	rseq_slice_yield		sys_rseq_slice_yield
 472	common	fchroot				sys_fchroot
+473	common	set_robust_list2		sys_set_robust_list2
diff --git a/arch/sparc/kernel/syscalls/syscall.tbl b/arch/sparc/kernel/syscalls/syscall.tbl
index 5b9fe0e8140f..3c01fa1cd885 100644
--- a/arch/sparc/kernel/syscalls/syscall.tbl
+++ b/arch/sparc/kernel/syscalls/syscall.tbl
@@ -518,3 +518,4 @@
 470	common	listns				sys_listns
 471	common	rseq_slice_yield		sys_rseq_slice_yield
 472	common	fchroot				sys_fchroot
+473	common	set_robust_list2		sys_set_robust_list2
diff --git a/arch/x86/entry/syscalls/syscall_32.tbl b/arch/x86/entry/syscalls/syscall_32.tbl
index 2c172ef48dfd..11ebbf074920 100644
--- a/arch/x86/entry/syscalls/syscall_32.tbl
+++ b/arch/x86/entry/syscalls/syscall_32.tbl
@@ -478,3 +478,4 @@
 470	i386	listns			sys_listns
 471	i386	rseq_slice_yield	sys_rseq_slice_yield
 472	i386	fchroot			sys_fchroot
+473	i386	set_robust_list2	sys_set_robust_list2
diff --git a/arch/x86/entry/syscalls/syscall_64.tbl b/arch/x86/entry/syscalls/syscall_64.tbl
index d5b6045b0090..53398e8d4981 100644
--- a/arch/x86/entry/syscalls/syscall_64.tbl
+++ b/arch/x86/entry/syscalls/syscall_64.tbl
@@ -397,6 +397,7 @@
 470	common	listns			sys_listns
 471	common	rseq_slice_yield	sys_rseq_slice_yield
 472	common	fchroot			sys_fchroot
+473	common	set_robust_list2	sys_set_robust_list2
 
 #
 # Due to a historical design error, certain syscalls are numbered differently
diff --git a/arch/xtensa/kernel/syscalls/syscall.tbl b/arch/xtensa/kernel/syscalls/syscall.tbl
index d354bb231796..7ba9d6993800 100644
--- a/arch/xtensa/kernel/syscalls/syscall.tbl
+++ b/arch/xtensa/kernel/syscalls/syscall.tbl
@@ -443,3 +443,4 @@
 470	common	listns				sys_listns
 471	common	rseq_slice_yield		sys_rseq_slice_yield
 472	common	fchroot				sys_fchroot
+473	common	set_robust_list2		sys_set_robust_list2
diff --git a/include/uapi/asm-generic/unistd.h b/include/uapi/asm-generic/unistd.h
index 5b7e77a7c736..7525e0add809 100644
--- a/include/uapi/asm-generic/unistd.h
+++ b/include/uapi/asm-generic/unistd.h
@@ -867,8 +867,11 @@ __SYSCALL(__NR_rseq_slice_yield, sys_rseq_slice_yield)
 #define __NR_fchroot 472
 __SYSCALL(__NR_fchroot, sys_fchroot)
 
+#define __NR_set_robust_list2 473
+__SYSCALL(__NR_set_robust_list2, sys_set_robust_list2)
+
 #undef __NR_syscalls
-#define __NR_syscalls 473
+#define __NR_syscalls 474
 
 /*
  * 32 bit systems traditionally used different
diff --git a/scripts/syscall.tbl b/scripts/syscall.tbl
index 0ab531605120..c8d261cb8762 100644
--- a/scripts/syscall.tbl
+++ b/scripts/syscall.tbl
@@ -413,3 +413,4 @@
 470	common	listns				sys_listns
 471	common	rseq_slice_yield		sys_rseq_slice_yield
 472	common	fchroot				sys_fchroot
+473	common	set_robust_list2		sys_set_robust_list2

-- 
2.56.1


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

* [PATCH v8 07/10] futex: Wire up get_robust_list2 syscall
  2026-11-15 17:31 [PATCH v8 00/10] futex: Create {set,get}_robust_list2() syscalls André Almeida
                   ` (5 preceding siblings ...)
  2026-11-15 17:31 ` [PATCH v8 06/10] futex: Wire up set_robust_list2 syscall André Almeida
@ 2026-11-15 17:31 ` André Almeida
  2026-11-15 17:31 ` [PATCH v8 08/10] selftests/futex: Expand for set_robust_list2() André Almeida
                   ` (2 subsequent siblings)
  9 siblings, 0 replies; 14+ messages in thread
From: André Almeida @ 2026-11-15 17:31 UTC (permalink / raw)
  To: Ingo Molnar, Peter Zijlstra, Darren Hart, Davidlohr Bueso,
	Arnd Bergmann, Sebastian Andrzej Siewior, Waiman Long,
	Ryan Houdek, Thomas Gleixner
  Cc: linux-kernel, linux-kselftest, linux-api, kernel-dev, André Almeida

Wire up the new get_robust_list2 syscall in all available architectures.

Signed-off-by: André Almeida <andrealmeid@igalia.com>
---
 arch/alpha/kernel/syscalls/syscall.tbl      | 1 +
 arch/arm/tools/syscall.tbl                  | 1 +
 arch/m68k/kernel/syscalls/syscall.tbl       | 1 +
 arch/microblaze/kernel/syscalls/syscall.tbl | 1 +
 arch/mips/kernel/syscalls/syscall_n32.tbl   | 1 +
 arch/mips/kernel/syscalls/syscall_n64.tbl   | 1 +
 arch/mips/kernel/syscalls/syscall_o32.tbl   | 1 +
 arch/parisc/kernel/syscalls/syscall.tbl     | 1 +
 arch/powerpc/kernel/syscalls/syscall.tbl    | 1 +
 arch/s390/kernel/syscalls/syscall.tbl       | 1 +
 arch/sh/kernel/syscalls/syscall.tbl         | 1 +
 arch/sparc/kernel/syscalls/syscall.tbl      | 1 +
 arch/x86/entry/syscalls/syscall_32.tbl      | 1 +
 arch/x86/entry/syscalls/syscall_64.tbl      | 1 +
 arch/xtensa/kernel/syscalls/syscall.tbl     | 1 +
 include/uapi/asm-generic/unistd.h           | 4 +++-
 scripts/syscall.tbl                         | 1 +
 17 files changed, 19 insertions(+), 1 deletion(-)

diff --git a/arch/alpha/kernel/syscalls/syscall.tbl b/arch/alpha/kernel/syscalls/syscall.tbl
index cdf641845014..e26df2cf9de7 100644
--- a/arch/alpha/kernel/syscalls/syscall.tbl
+++ b/arch/alpha/kernel/syscalls/syscall.tbl
@@ -513,3 +513,4 @@
 581	common	rseq_slice_yield		sys_rseq_slice_yield
 582	common	fchroot				sys_fchroot
 583	common	set_robust_list2		sys_set_robust_list2
+584	common	get_robust_list2		sys_get_robust_list2
diff --git a/arch/arm/tools/syscall.tbl b/arch/arm/tools/syscall.tbl
index c287461803ff..0268a887f90d 100644
--- a/arch/arm/tools/syscall.tbl
+++ b/arch/arm/tools/syscall.tbl
@@ -488,3 +488,4 @@
 471	common	rseq_slice_yield		sys_rseq_slice_yield
 472	common	fchroot				sys_fchroot
 473	common	set_robust_list2		sys_set_robust_list2
+474	common	get_robust_list2		sys_get_robust_list2
diff --git a/arch/m68k/kernel/syscalls/syscall.tbl b/arch/m68k/kernel/syscalls/syscall.tbl
index beb0ba7f350c..91cc1ea407ec 100644
--- a/arch/m68k/kernel/syscalls/syscall.tbl
+++ b/arch/m68k/kernel/syscalls/syscall.tbl
@@ -473,3 +473,4 @@
 471	common	rseq_slice_yield		sys_rseq_slice_yield
 472	common	fchroot				sys_fchroot
 473	common  set_robust_list2		sys_set_robust_list2
+474	common  get_robust_list2		sys_get_robust_list2
diff --git a/arch/microblaze/kernel/syscalls/syscall.tbl b/arch/microblaze/kernel/syscalls/syscall.tbl
index bf04133f7239..18a59b24724c 100644
--- a/arch/microblaze/kernel/syscalls/syscall.tbl
+++ b/arch/microblaze/kernel/syscalls/syscall.tbl
@@ -479,3 +479,4 @@
 471	common	rseq_slice_yield		sys_rseq_slice_yield
 472	common	fchroot				sys_fchroot
 473	common	set_robust_list2		sys_set_robust_list2
+474	common	get_robust_list2		sys_get_robust_list2
diff --git a/arch/mips/kernel/syscalls/syscall_n32.tbl b/arch/mips/kernel/syscalls/syscall_n32.tbl
index 5b5b217ee7f3..f498b01178e4 100644
--- a/arch/mips/kernel/syscalls/syscall_n32.tbl
+++ b/arch/mips/kernel/syscalls/syscall_n32.tbl
@@ -412,3 +412,4 @@
 471	n32	rseq_slice_yield		sys_rseq_slice_yield
 472	n32	fchroot				sys_fchroot
 473	n32	set_robust_list2		sys_set_robust_list2
+474	n32	get_robust_list2		sys_get_robust_list2
diff --git a/arch/mips/kernel/syscalls/syscall_n64.tbl b/arch/mips/kernel/syscalls/syscall_n64.tbl
index 6f203cb3a558..b12328d537e3 100644
--- a/arch/mips/kernel/syscalls/syscall_n64.tbl
+++ b/arch/mips/kernel/syscalls/syscall_n64.tbl
@@ -388,3 +388,4 @@
 471	n64	rseq_slice_yield		sys_rseq_slice_yield
 472	n64	fchroot				sys_fchroot
 473	n64	set_robust_list2		sys_set_robust_list2
+474	n64	get_robust_list2		sys_get_robust_list2
diff --git a/arch/mips/kernel/syscalls/syscall_o32.tbl b/arch/mips/kernel/syscalls/syscall_o32.tbl
index d170650521a7..3c8e3890644f 100644
--- a/arch/mips/kernel/syscalls/syscall_o32.tbl
+++ b/arch/mips/kernel/syscalls/syscall_o32.tbl
@@ -461,3 +461,4 @@
 471	o32	rseq_slice_yield		sys_rseq_slice_yield
 472	o32	fchroot				sys_fchroot
 473	o32	set_robust_list2		sys_set_robust_list2
+474	o32	get_robust_list2		sys_get_robust_list2
diff --git a/arch/parisc/kernel/syscalls/syscall.tbl b/arch/parisc/kernel/syscalls/syscall.tbl
index f9317ff28e37..f746f152cd51 100644
--- a/arch/parisc/kernel/syscalls/syscall.tbl
+++ b/arch/parisc/kernel/syscalls/syscall.tbl
@@ -472,3 +472,4 @@
 471	common	rseq_slice_yield		sys_rseq_slice_yield
 472	common	fchroot				sys_fchroot
 473	common	set_robust_list2		sys_set_robust_list2
+474	common	get_robust_list2		sys_get_robust_list2
diff --git a/arch/powerpc/kernel/syscalls/syscall.tbl b/arch/powerpc/kernel/syscalls/syscall.tbl
index acb9d446d1f6..b785d6861963 100644
--- a/arch/powerpc/kernel/syscalls/syscall.tbl
+++ b/arch/powerpc/kernel/syscalls/syscall.tbl
@@ -564,3 +564,4 @@
 471	nospu	rseq_slice_yield		sys_rseq_slice_yield
 472	common	fchroot				sys_fchroot
 473	common	set_robust_list2		sys_set_robust_list2
+474	common	get_robust_list2		sys_get_robust_list2
diff --git a/arch/s390/kernel/syscalls/syscall.tbl b/arch/s390/kernel/syscalls/syscall.tbl
index 987e026ffbcf..eb0c5bf1d71f 100644
--- a/arch/s390/kernel/syscalls/syscall.tbl
+++ b/arch/s390/kernel/syscalls/syscall.tbl
@@ -400,3 +400,4 @@
 471	common	rseq_slice_yield		sys_rseq_slice_yield
 472	common	fchroot				sys_fchroot
 473	common	set_robust_list2		sys_set_robust_list2
+474	common	get_robust_list2		sys_get_robust_list2
diff --git a/arch/sh/kernel/syscalls/syscall.tbl b/arch/sh/kernel/syscalls/syscall.tbl
index c944333c1990..520ec9072ce3 100644
--- a/arch/sh/kernel/syscalls/syscall.tbl
+++ b/arch/sh/kernel/syscalls/syscall.tbl
@@ -477,3 +477,4 @@
 471	common	rseq_slice_yield		sys_rseq_slice_yield
 472	common	fchroot				sys_fchroot
 473	common	set_robust_list2		sys_set_robust_list2
+474	common	get_robust_list2		sys_get_robust_list2
diff --git a/arch/sparc/kernel/syscalls/syscall.tbl b/arch/sparc/kernel/syscalls/syscall.tbl
index 3c01fa1cd885..8d332ffde99f 100644
--- a/arch/sparc/kernel/syscalls/syscall.tbl
+++ b/arch/sparc/kernel/syscalls/syscall.tbl
@@ -519,3 +519,4 @@
 471	common	rseq_slice_yield		sys_rseq_slice_yield
 472	common	fchroot				sys_fchroot
 473	common	set_robust_list2		sys_set_robust_list2
+474	common	get_robust_list2		sys_get_robust_list2
diff --git a/arch/x86/entry/syscalls/syscall_32.tbl b/arch/x86/entry/syscalls/syscall_32.tbl
index 11ebbf074920..be72e54ce2fd 100644
--- a/arch/x86/entry/syscalls/syscall_32.tbl
+++ b/arch/x86/entry/syscalls/syscall_32.tbl
@@ -479,3 +479,4 @@
 471	i386	rseq_slice_yield	sys_rseq_slice_yield
 472	i386	fchroot			sys_fchroot
 473	i386	set_robust_list2	sys_set_robust_list2
+474	i386	get_robust_list2	sys_get_robust_list2
diff --git a/arch/x86/entry/syscalls/syscall_64.tbl b/arch/x86/entry/syscalls/syscall_64.tbl
index 53398e8d4981..d5f91d276e75 100644
--- a/arch/x86/entry/syscalls/syscall_64.tbl
+++ b/arch/x86/entry/syscalls/syscall_64.tbl
@@ -398,6 +398,7 @@
 471	common	rseq_slice_yield	sys_rseq_slice_yield
 472	common	fchroot			sys_fchroot
 473	common	set_robust_list2	sys_set_robust_list2
+474	common	get_robust_list2	sys_get_robust_list2
 
 #
 # Due to a historical design error, certain syscalls are numbered differently
diff --git a/arch/xtensa/kernel/syscalls/syscall.tbl b/arch/xtensa/kernel/syscalls/syscall.tbl
index 7ba9d6993800..4908baf60363 100644
--- a/arch/xtensa/kernel/syscalls/syscall.tbl
+++ b/arch/xtensa/kernel/syscalls/syscall.tbl
@@ -444,3 +444,4 @@
 471	common	rseq_slice_yield		sys_rseq_slice_yield
 472	common	fchroot				sys_fchroot
 473	common	set_robust_list2		sys_set_robust_list2
+474	common	get_robust_list2		sys_get_robust_list2
diff --git a/include/uapi/asm-generic/unistd.h b/include/uapi/asm-generic/unistd.h
index 7525e0add809..3d84f306e677 100644
--- a/include/uapi/asm-generic/unistd.h
+++ b/include/uapi/asm-generic/unistd.h
@@ -869,9 +869,11 @@ __SYSCALL(__NR_fchroot, sys_fchroot)
 
 #define __NR_set_robust_list2 473
 __SYSCALL(__NR_set_robust_list2, sys_set_robust_list2)
+#define __NR_get_robust_list2 474
+__SYSCALL(__NR_get_robust_list2, sys_get_robust_list2)
 
 #undef __NR_syscalls
-#define __NR_syscalls 474
+#define __NR_syscalls 475
 
 /*
  * 32 bit systems traditionally used different
diff --git a/scripts/syscall.tbl b/scripts/syscall.tbl
index c8d261cb8762..b4fb5e1a2141 100644
--- a/scripts/syscall.tbl
+++ b/scripts/syscall.tbl
@@ -414,3 +414,4 @@
 471	common	rseq_slice_yield		sys_rseq_slice_yield
 472	common	fchroot				sys_fchroot
 473	common	set_robust_list2		sys_set_robust_list2
+474	common	get_robust_list2		sys_get_robust_list2

-- 
2.56.1


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

* [PATCH v8 08/10] selftests/futex: Expand for set_robust_list2()
  2026-11-15 17:31 [PATCH v8 00/10] futex: Create {set,get}_robust_list2() syscalls André Almeida
                   ` (6 preceding siblings ...)
  2026-11-15 17:31 ` [PATCH v8 07/10] futex: Wire up get_robust_list2 syscall André Almeida
@ 2026-11-15 17:31 ` André Almeida
  2026-11-15 17:31 ` [PATCH v8 09/10] selftests/futex: Expand for get_robust_list2() André Almeida
  2026-11-15 17:31 ` [PATCH v8 10/10] futex: Use new robust list API internally André Almeida
  9 siblings, 0 replies; 14+ messages in thread
From: André Almeida @ 2026-11-15 17:31 UTC (permalink / raw)
  To: Ingo Molnar, Peter Zijlstra, Darren Hart, Davidlohr Bueso,
	Arnd Bergmann, Sebastian Andrzej Siewior, Waiman Long,
	Ryan Houdek, Thomas Gleixner
  Cc: linux-kernel, linux-kselftest, linux-api, kernel-dev, André Almeida

Reuse the same selftest for the original set_robust_list() syscall for
the new set_robust_list2() syscall. Use kselftest variants feature to
run the relevant tests for both interfaces. Create new test cases for
checking invalid parameters, the ability to correctly set multiple lists
for the same task, and to use 32-bit lists in a 64-bit task.

Signed-off-by: André Almeida <andrealmeid@igalia.com>
---
 .../selftests/futex/functional/robust_list.c       | 465 +++++++++++++++++++--
 1 file changed, 431 insertions(+), 34 deletions(-)

diff --git a/tools/testing/selftests/futex/functional/robust_list.c b/tools/testing/selftests/futex/functional/robust_list.c
index ddb610149857..7666b9a64501 100644
--- a/tools/testing/selftests/futex/functional/robust_list.c
+++ b/tools/testing/selftests/futex/functional/robust_list.c
@@ -49,6 +49,35 @@
 # define BUILD_64
 #endif
 
+#ifndef SYS_set_robust_list2
+# define SYS_set_robust_list2 473
+
+enum robust_list_cmd {
+	FUTEX_ROBUST_LIST_CMD_CREATE_64,
+	FUTEX_ROBUST_LIST_CMD_CREATE_32,
+	FUTEX_ROBUST_LIST_CMD_MODIFY_64,
+	FUTEX_ROBUST_LIST_CMD_MODIFY_32,
+	FUTEX_ROBUST_LIST_CMD_LIST_LIMIT,
+	FUTEX_ROBUST_LIST_CMD_USER_MAX,
+
+	/*
+	 * Kernel internal, rejected for user space
+	 */
+	FUTEX_ROBUST_LIST_SET_NATIVE = 128,
+	FUTEX_ROBUST_LIST_SET_COMPAT,
+};
+
+struct robust_list32 {
+	uint32_t next;
+};
+
+struct robust_list_head32 {
+	struct robust_list32	list;
+	int32_t			futex_offset;
+	uint32_t		list_op_pending;
+};
+#endif
+
 static pthread_barrier_t barrier, barrier2;
 
 static int set_robust_list(struct robust_list_head *head, size_t len)
@@ -67,6 +96,65 @@ static int sys_futex_robust_unlock(_Atomic(uint32_t) *uaddr, unsigned int op, in
 	return syscall(SYS_futex, uaddr, op, val, NULL, list_op_pending, val3, 0);
 }
 
+static int set_robust_list2(struct robust_list_head *head, enum robust_list_cmd cmd,
+			    unsigned int index, unsigned int flags)
+{
+	return syscall(SYS_set_robust_list2, head, cmd, index, flags, 0, 0);
+}
+
+static bool robust_list2_support(void)
+{
+	int ret = set_robust_list2(NULL, FUTEX_ROBUST_LIST_CMD_LIST_LIMIT, 0, 0);
+
+	if (ret == -1 && errno == ENOSYS)
+		return false;
+
+	return true;
+}
+
+/*
+ * Return the set command according to the app bitness
+ */
+static int get_cmd_create(void)
+{
+	return sizeof(uintptr_t) == 8 ? FUTEX_ROBUST_LIST_CMD_CREATE_64 :
+	       FUTEX_ROBUST_LIST_CMD_CREATE_32;
+}
+
+static int get_cmd_modify(void)
+{
+	return sizeof(uintptr_t) == 8 ? FUTEX_ROBUST_LIST_CMD_MODIFY_64 :
+	       FUTEX_ROBUST_LIST_CMD_MODIFY_32;
+}
+
+FIXTURE(robust_api) {};
+
+FIXTURE_VARIANT(robust_api)
+{
+	bool robust2;
+};
+
+FIXTURE_SETUP(robust_api)
+{
+	if (!variant->robust2)
+		return;
+
+	if (!robust_list2_support())
+		SKIP(return, "robust_list2 not supported");
+}
+
+FIXTURE_TEARDOWN(robust_api) {}
+
+FIXTURE_VARIANT_ADD(robust_api, robust1)
+{
+	.robust2 = false,
+};
+
+FIXTURE_VARIANT_ADD(robust_api, robust2)
+{
+	.robust2 = true,
+};
+
 /*
  * Basic lock struct, contains just the futex word and the robust list element
  * Real implementations have also a *prev to easily walk in the list
@@ -76,6 +164,12 @@ typedef _Atomic(unsigned int) atomic_futex_t;
 struct lock_struct {
 	atomic_futex_t		futex;
 	struct robust_list	list;
+	bool			robust2;
+};
+
+struct lock_struct32 {
+	_Atomic(uint32_t)	futex;
+	struct robust_list32	list;
 };
 
 struct child_args {
@@ -118,20 +212,32 @@ static int create_child(struct __test_metadata *_metadata, int (*fn)(void *arg),
 /*
  * Helper function to prepare and register a robust list
  */
-static int set_list(struct robust_list_head *head)
+static int set_list(struct robust_list_head *head, bool robust2, int *index)
 {
 	int ret;
 
-	ret = set_robust_list(head, sizeof(*head));
-	if (ret)
-		return ret;
-
 	head->futex_offset = (size_t) offsetof(struct lock_struct, futex) -
 			     (size_t) offsetof(struct lock_struct, list);
 	head->list.next = &head->list;
 	head->list_op_pending = NULL;
 
-	return 0;
+	if (!robust2)
+		return set_robust_list(head, sizeof(*head));
+
+	ret = set_robust_list2(head, get_cmd_create(), 0, 0);
+
+	if (ret >= 0 && index)
+		*index = ret;
+
+	return ret;
+}
+
+/*
+ * Change a given list index to a different head
+ */
+static int modify_list(struct robust_list_head *head, int index)
+{
+	return set_robust_list2(head, get_cmd_modify(), index, 0);
 }
 
 /*
@@ -203,12 +309,12 @@ static int child_fn_lock(void *arg)
 	struct __test_metadata *_metadata = cargs->_metadata;
 	struct lock_struct *lock = cargs->arg;
 	struct robust_list_head head;
-	int ret;
+	int ret, index;
 
 	free(cargs);
 
-	ret = set_list(&head);
-	ASSERT_EQ(ret, 0)
+	ret = set_list(&head, lock->robust2, &index);
+	ASSERT_NE(ret, -1)
 		TH_LOG("set_robust_list error");
 
 	ret = mutex_lock(lock, &head, false);
@@ -233,15 +339,17 @@ static int child_fn_lock(void *arg)
  * in the robust list and die. The parent thread will wait on this futex, and
  * should be waken up when the child exits.
  */
-TEST(test_robustness)
+TEST_F(robust_api, test_robustness)
 {
 	struct lock_struct lock = { .futex = 0 };
 	atomic_futex_t *futex = &lock.futex;
 	struct robust_list_head head;
-	int ret, pid, wstatus;
+	int ret, pid, wstatus, index;
 
-	ret = set_list(&head);
-	ASSERT_EQ(ret, 0);
+	lock.robust2 = variant->robust2;
+
+	ret = set_list(&head, lock.robust2, &index);
+	ASSERT_NE(ret, -1);
 
 	/*
 	 * Lets use a barrier to ensure that the child thread takes the lock
@@ -281,7 +389,7 @@ TEST(test_set_robust_list_invalid_size)
 	int ret;
 
 	ret = set_robust_list(&head, head_size);
-	ASSERT_EQ(ret, 0);
+	ASSERT_GE(ret, 0);
 
 	ret = set_robust_list(&head, head_size * 2);
 	ASSERT_EQ(ret, -1);
@@ -296,6 +404,53 @@ TEST(test_set_robust_list_invalid_size)
 	ASSERT_EQ(errno, EINVAL);
 }
 
+/*
+ * Test invalid parameters
+ */
+TEST(test_set_robust_list2_inval)
+{
+	struct robust_list_head head;
+	int i, ret, index, list_limit;
+
+	if (!robust_list2_support())
+		SKIP(return, "robust_list2 not supported\n");
+
+	/* Bad flag */
+	ret = set_robust_list2(&head, get_cmd_create(), 0, 999);
+	ASSERT_EQ(ret, -1);
+	ASSERT_EQ(errno, EINVAL);
+
+	/* List out of range */
+	list_limit = set_robust_list2(NULL, FUTEX_ROBUST_LIST_CMD_LIST_LIMIT, 0, 0);
+	ASSERT_GT(list_limit, 1);
+
+	for (i = 0; i < list_limit; i++) {
+		ret = set_list(&head, true, &index);
+		ASSERT_EQ(ret, i);
+	}
+
+	ret = set_list(&head, true, &index);
+	ASSERT_EQ(ret, -1);
+	ASSERT_EQ(errno, ENOSPC);
+
+	/* clear the list */
+	for (i = 0; i < list_limit; i++)
+		modify_list(NULL, i);
+
+#ifdef BUILD_64
+	/* Create a 64-bit entry, and try to set it as 32-bit */
+	ret = set_robust_list2(&head, FUTEX_ROBUST_LIST_CMD_CREATE_64, 0, 0);
+	ASSERT_GE(ret, 0);
+
+	ret = set_robust_list2(&head, FUTEX_ROBUST_LIST_CMD_MODIFY_64, 0, 0);
+	ASSERT_GE(ret, 0);
+
+	ret = set_robust_list2(&head, FUTEX_ROBUST_LIST_CMD_MODIFY_32, 0, 0);
+	ASSERT_NE(ret, 0);
+#endif
+
+}
+
 /*
  * Test get_robust_list with pid = 0, getting the list of the running thread
  */
@@ -388,12 +543,12 @@ static int child_fn_lock_with_error(void *arg)
 	struct __test_metadata *_metadata = cargs->_metadata;
 	struct lock_struct *lock = cargs->arg;
 	struct robust_list_head head;
-	int ret;
+	int ret, index;
 
 	free(cargs);
 
-	ret = set_list(&head);
-	ASSERT_EQ(ret, 0)
+	ret = set_list(&head, lock->robust2, &index);
+	ASSERT_NE(ret, -1)
 		TH_LOG("set_robust_list error");
 
 	ret = mutex_lock(lock, &head, true);
@@ -413,15 +568,17 @@ static int child_fn_lock_with_error(void *arg)
  * earlier, just after setting list_op_pending and taking the lock, to test the
  * list_op_pending mechanism
  */
-TEST(test_set_list_op_pending)
+TEST_F(robust_api, test_set_list_op_pending)
 {
 	struct lock_struct lock = { .futex = 0 };
 	atomic_futex_t *futex = &lock.futex;
 	struct robust_list_head head;
-	int ret, wstatus;
+	int ret, wstatus, index;
 
-	ret = set_list(&head);
-	ASSERT_EQ(ret, 0);
+	lock.robust2 = variant->robust2;
+
+	ret = set_list(&head, lock.robust2, &index);
+	ASSERT_NE(ret, -1);
 
 	ret = pthread_barrier_init(&barrier, NULL, 2);
 	ASSERT_EQ(ret, 0);
@@ -450,11 +607,11 @@ static int child_lock_holder(void *arg)
 	struct child_args *cargs = arg;
 	struct lock_struct *locks = cargs->arg;
 	struct robust_list_head head;
-	int i;
+	int i, index;
 
 	free(cargs);
 
-	set_list(&head);
+	set_list(&head, locks[0].robust2, &index);
 
 	for (i = 0; i < CHILD_NR; i++) {
 		locks[i].futex = 0;
@@ -495,17 +652,23 @@ static int child_wait_lock(void *arg)
  * Test a robust list of more than one element. All the waiters should wake when
  * the holder dies
  */
-TEST(test_robust_list_multiple_elements)
+TEST_F(robust_api, test_robust_list_multiple_elements)
 {
 	struct lock_struct locks[CHILD_NR];
 	pid_t pids[CHILD_NR + 1];
 	int i, ret, wstatus;
 
+	if (variant->robust2 && !robust_list2_support())
+		SKIP(return, "robust_list2 not supported\n");
+
+	locks[0].robust2 = variant->robust2;
+
 	ret = pthread_barrier_init(&barrier, NULL, 2);
 	ASSERT_EQ(ret, 0);
 	ret = pthread_barrier_init(&barrier2, NULL, CHILD_NR + 1);
 	ASSERT_EQ(ret, 0);
 
+
 	pids[0] = create_child(_metadata, &child_lock_holder, &locks);
 	ASSERT_NE(pids[0], -1);
 
@@ -532,18 +695,112 @@ TEST(test_robust_list_multiple_elements)
 		TH_LOG("One or more children failed");
 }
 
+static int child_lock_holder_multiple_lists(void *arg)
+{
+	struct child_args *cargs = arg;
+	struct __test_metadata *_metadata = cargs->_metadata;
+	struct lock_struct *locks = cargs->arg;
+	struct robust_list_head *heads;
+	int i, list_limit, index, ret;
+
+	free(cargs);
+
+	list_limit = set_robust_list2(NULL, FUTEX_ROBUST_LIST_CMD_LIST_LIMIT, 0, 0);
+	ASSERT_GT(list_limit, 1);
+
+	heads = malloc(list_limit * sizeof(*heads));
+	ASSERT_TRUE((uintptr_t) heads);
+
+	/*
+	 * Try to clear any exiting list, ignore errors if they didn't exit
+	 */
+	for (i = 0; i < list_limit; i++)
+		modify_list(NULL, i);
+
+	/*
+	 * Given that this thread has no robust list attached yet, it should
+	 * get as return all available lists in order [0, list_limit)
+	 */
+	for (i = 0; i < list_limit; i++) {
+		ret = set_list(&heads[i], true, &index);
+		ASSERT_EQ(ret, i);
+		locks[i].futex = 0;
+		mutex_lock(&locks[i], &heads[i], false);
+	}
+
+	pthread_barrier_wait(&barrier);
+	pthread_barrier_wait(&barrier2);
+
+	/* See comment at child_fn_lock() */
+	usleep(SLEEP_US * 10);
+
+	return 0;
+}
+
+/*
+ * Similar to test_robust_list_multiple_elements, but instead of one list with
+ * several elements, create several lists with one element.
+ */
+TEST(test_robust_list_multiple_lists)
+{
+	int i, ret, wstatus, list_limit;
+	struct lock_struct *locks;
+	pid_t *pids;
+
+	if (!robust_list2_support())
+		SKIP(return, "robust_list2 not supported\n");
+
+	list_limit = set_robust_list2(NULL, FUTEX_ROBUST_LIST_CMD_LIST_LIMIT, 0, 0);
+	ASSERT_GT(list_limit, 1);
+
+	locks = malloc(list_limit * sizeof(*locks));
+	ASSERT_NE(locks, NULL);
+
+	pids = malloc(list_limit * sizeof(*pids));
+	ASSERT_NE(pids, NULL);
+
+	ret = pthread_barrier_init(&barrier, NULL, 2);
+	ASSERT_EQ(ret, 0);
+	ret = pthread_barrier_init(&barrier2, NULL, list_limit + 1);
+	ASSERT_EQ(ret, 0);
+
+	pids[0] = create_child(_metadata, &child_lock_holder_multiple_lists, locks);
+
+	/* Wait until the locker thread takes the look */
+	pthread_barrier_wait(&barrier);
+
+	for (i = 0; i < list_limit; i++)
+		pids[i+1] = create_child(_metadata, &child_wait_lock, &locks[i]);
+
+	/* Wait for all children to return */
+	ret = 0;
+
+	for (i = 0; i < list_limit; i++) {
+		waitpid(pids[i], &wstatus, 0);
+		if (WEXITSTATUS(wstatus))
+			ret = -1;
+	}
+
+	pthread_barrier_destroy(&barrier);
+	pthread_barrier_destroy(&barrier2);
+
+	free(locks);
+	free(pids);
+}
+
 static int child_circular_list(void *arg)
 {
 	struct child_args *cargs = arg;
+	bool robust2 = cargs->arg;
 	struct __test_metadata *_metadata = cargs->_metadata;
 	static struct lock_struct a, b, c;
 	struct robust_list_head head;
-	int ret;
+	int ret, index;
 
 	free(cargs);
 
-	ret = set_list(&head);
-	ASSERT_EQ(ret, 0)
+	ret = set_list(&head, robust2, &index);
+	ASSERT_NE(ret, -1)
 		TH_LOG("set_list error");
 
 	head.list.next = &a.list;
@@ -563,11 +820,13 @@ static int child_circular_list(void *arg)
  * while processing it so it won't be trapped in an infinite loop while handling
  * a process exit
  */
-TEST(test_circular_list)
+TEST_F(robust_api, test_circular_list)
 {
+	bool robust2 = variant->robust2;
 	int wstatus;
 	pid_t pid;
 
+	create_child(_metadata, child_circular_list, (void *) robust2);
 	pid = create_child(_metadata, child_circular_list, NULL);
 	ASSERT_NE(pid, -1);
 
@@ -660,8 +919,8 @@ TEST_F(vdso_unlock, test_robust_try_unlock_uncontended)
 
 	*futex = tid;
 
-	ret = set_list(&head);
-	if (ret)
+	ret = set_list(&head, false, NULL);
+	if (ret == -1)
 		ksft_test_result_fail("set_robust_list error\n");
 
 	head.list_op_pending = &lock.list;
@@ -700,8 +959,8 @@ TEST_F(vdso_unlock, test_robust_try_unlock_contended)
 
 	*futex = tid | FUTEX_WAITERS;
 
-	ret = set_list(&head);
-	if (ret)
+	ret = set_list(&head, false, NULL);
+	if (ret == -1)
 		ksft_test_result_fail("set_robust_list error\n");
 
 	head.list_op_pending = &lock.list;
@@ -783,8 +1042,8 @@ TEST_F(futex_op, test_futex_robust_unlock)
 
 	*futex = tid | FUTEX_WAITERS;
 
-	ret = set_list(&head);
-	if (ret)
+	ret = set_list(&head, false, 0);
+	if (ret == -1)
 		ksft_test_result_fail("set_robust_list error\n");
 
 	head.list_op_pending = &lock.list;
@@ -806,4 +1065,142 @@ TEST_F(futex_op, test_futex_robust_unlock)
 	ASSERT_EQ((uintptr_t)(unsigned long)head.list_op_pending, exp);
 }
 
+/*
+ * 32-bit version of child_lock_holder.
+ */
+static int child_lock_holder32(void *arg)
+{
+	struct child_args *cargs = arg;
+	struct lock_struct32 *locks = cargs->arg;
+	struct __test_metadata *_metadata = cargs->_metadata;
+	struct robust_list_head32 *head;
+	pid_t tid = gettid();
+	int i, ret;
+
+	head = mmap((void *)0x10000, sizeof(*head), PROT_READ | PROT_WRITE,
+		    MAP_FIXED_NOREPLACE | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+
+	ASSERT_TRUE((uintptr_t) head);
+	ASSERT_LT(((uint32_t)(uintptr_t) head), 0x7FFFFFFF);
+
+	head->futex_offset = (uint32_t) ((size_t) offsetof(struct lock_struct32, futex) -
+			     (size_t) offsetof(struct lock_struct32, list));
+	head->list.next = (uint32_t)(uintptr_t) &head->list;
+	head->list_op_pending = (uint32_t)(uintptr_t) NULL;
+
+	ret = set_robust_list2((struct robust_list_head *) head,
+			FUTEX_ROBUST_LIST_CMD_CREATE_32, 0, 0);
+	ASSERT_GE(ret, 0);
+
+	/*
+	 * Take all the locks and insert them in the list
+	 */
+	for (i = 0; i < CHILD_NR; i++) {
+		struct robust_list32 *list = &head->list;
+
+		locks[i].futex = tid;
+
+		while (list->next != (uint32_t)(uintptr_t) &head->list)
+			list = (struct robust_list32 *)(uintptr_t) list->next;
+
+		list->next = (uint32_t)(uintptr_t) &locks[i].list;
+		locks[i].list.next = (uint32_t)(uintptr_t) &head->list;
+	}
+
+	pthread_barrier_wait(&barrier);
+	pthread_barrier_wait(&barrier2);
+
+	/* See comment at child_fn_lock() */
+	usleep(SLEEP_US);
+
+	/* Exit holding all the locks */
+	return 0;
+}
+
+static int child_wait_lock32(void *arg)
+{
+	struct child_args *cargs = arg;
+	struct __test_metadata *_metadata = cargs->_metadata;
+	struct lock_struct32 *lock = cargs->arg;
+	atomic_futex_t *futex;
+	struct timespec to;
+	pid_t tid;
+	int ret;
+
+	futex = &lock->futex;
+
+	pthread_barrier_wait(&barrier2);
+
+	to.tv_sec = FUTEX_TIMEOUT;
+	to.tv_nsec = 0;
+
+	tid = atomic_load(futex);
+
+	/* Kernel ignores futexes without the waiters flag */
+	tid |= FUTEX_WAITERS;
+	atomic_store(futex, tid);
+
+	ret = futex_wait((futex_t *) futex, tid, &to, 0);
+
+	ASSERT_EQ(ret, 0);
+	ASSERT_TRUE(lock->futex & FUTEX_OWNER_DIED);
+
+	return 0;
+}
+
+/*
+ * Test to create a 32-bit robust list in a 64-bit kernel. Replicate
+ * test_robust_list_multiple_elements, but it's simplified: don't do all the
+ * mutex lock dance, just insert futexes in the list and check if the kernel
+ * correctly walks the list and wake the threads
+ */
+TEST(test_32bit_lists)
+{
+	struct lock_struct32 *locks;
+	pid_t pids[CHILD_NR + 1];
+	int i, ret, wstatus;
+
+#ifndef BUILD_64
+	SKIP(return, "Test only for 64-bit\n");
+#endif
+
+	if (!robust_list2_support())
+		SKIP(return, "robust_list2 not supported\n");
+
+	locks = mmap((void *)0x20000, sizeof(*locks) * CHILD_NR,
+		     PROT_READ | PROT_WRITE,
+		     MAP_FIXED_NOREPLACE | MAP_PRIVATE | MAP_ANONYMOUS,
+		     -1, 0);
+
+	ASSERT_NE(locks, NULL);
+	ASSERT_LT((uintptr_t) locks, 0x7FFFFFFF);
+
+	ret = pthread_barrier_init(&barrier, NULL, 2);
+	ASSERT_EQ(ret, 0);
+	ret = pthread_barrier_init(&barrier2, NULL, CHILD_NR + 1);
+	ASSERT_EQ(ret, 0);
+
+	pids[0] = create_child(_metadata, &child_lock_holder32, locks);
+
+	/* Wait until the locker thread takes the look */
+	pthread_barrier_wait(&barrier);
+
+	for (i = 0; i < CHILD_NR; i++)
+		pids[i+1] = create_child(_metadata, &child_wait_lock32, &locks[i]);
+
+	/* Wait for all children to return */
+	ret = 0;
+
+	for (i = 0; i < CHILD_NR; i++) {
+		waitpid(pids[i], &wstatus, 0);
+		if (WEXITSTATUS(wstatus))
+			ret = -1;
+	}
+
+	pthread_barrier_destroy(&barrier);
+	pthread_barrier_destroy(&barrier2);
+
+	munmap(locks, sizeof(*locks) * CHILD_NR);
+}
+
 TEST_HARNESS_MAIN

-- 
2.56.1


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

* [PATCH v8 09/10] selftests/futex: Expand for get_robust_list2()
  2026-11-15 17:31 [PATCH v8 00/10] futex: Create {set,get}_robust_list2() syscalls André Almeida
                   ` (7 preceding siblings ...)
  2026-11-15 17:31 ` [PATCH v8 08/10] selftests/futex: Expand for set_robust_list2() André Almeida
@ 2026-11-15 17:31 ` André Almeida
  2026-11-15 17:31 ` [PATCH v8 10/10] futex: Use new robust list API internally André Almeida
  9 siblings, 0 replies; 14+ messages in thread
From: André Almeida @ 2026-11-15 17:31 UTC (permalink / raw)
  To: Ingo Molnar, Peter Zijlstra, Darren Hart, Davidlohr Bueso,
	Arnd Bergmann, Sebastian Andrzej Siewior, Waiman Long,
	Ryan Houdek, Thomas Gleixner
  Cc: linux-kernel, linux-kselftest, linux-api, kernel-dev, André Almeida

Reuse the same selftest for the original set_robust_list() syscall for
the new set_robust_list2() syscall. Use kselftest variants feature to
run the relevant tests for both interfaces. Create a new test case to
get different lists from the same task.

Signed-off-by: André Almeida <andrealmeid@igalia.com>
---
 .../selftests/futex/functional/robust_list.c       | 164 ++++++++++++++++++---
 1 file changed, 143 insertions(+), 21 deletions(-)

diff --git a/tools/testing/selftests/futex/functional/robust_list.c b/tools/testing/selftests/futex/functional/robust_list.c
index 7666b9a64501..3d97b948bc0a 100644
--- a/tools/testing/selftests/futex/functional/robust_list.c
+++ b/tools/testing/selftests/futex/functional/robust_list.c
@@ -51,6 +51,7 @@
 
 #ifndef SYS_set_robust_list2
 # define SYS_set_robust_list2 473
+# define SYS_get_robust_list2 474
 
 enum robust_list_cmd {
 	FUTEX_ROBUST_LIST_CMD_CREATE_64,
@@ -102,6 +103,12 @@ static int set_robust_list2(struct robust_list_head *head, enum robust_list_cmd
 	return syscall(SYS_set_robust_list2, head, cmd, index, flags, 0, 0);
 }
 
+static int get_robust_list2(int pid, struct robust_list_head **head,
+			    unsigned int index, unsigned int flags)
+{
+	return syscall(SYS_get_robust_list2, pid, head, index, flags);
+}
+
 static bool robust_list2_support(void)
 {
 	int ret = set_robust_list2(NULL, FUTEX_ROBUST_LIST_CMD_LIST_LIMIT, 0, 0);
@@ -240,6 +247,23 @@ static int modify_list(struct robust_list_head *head, int index)
 	return set_robust_list2(head, get_cmd_modify(), index, 0);
 }
 
+static int get_list(pid_t pid, struct robust_list_head **head, bool robust2, int index)
+{
+	int ret;
+
+	if (!robust2) {
+		size_t len_ptr;
+
+		ret = get_robust_list(pid, head, &len_ptr);
+		if (sizeof(**head) != len_ptr)
+			return -EINVAL;
+
+		return ret;
+	}
+
+	return get_robust_list2(pid, head, index, 0);
+}
+
 /*
  * A basic (and incomplete) mutex lock function with robustness
  */
@@ -454,40 +478,45 @@ TEST(test_set_robust_list2_inval)
 /*
  * Test get_robust_list with pid = 0, getting the list of the running thread
  */
-TEST(test_get_robust_list_self)
+TEST_F(robust_api, test_get_robust_list_self)
 {
 	struct robust_list_head head, head2, *get_head;
-	size_t head_size = sizeof(head), len_ptr;
-	int ret;
+	bool robust2 = variant->robust2;
+	int ret, index = 0;
 
-	ret = set_robust_list(&head, head_size);
-	ASSERT_EQ(ret, 0);
+	ret = set_list(&head, robust2, 0);
+	ASSERT_GE(ret, 0);
 
-	ret = get_robust_list(0, &get_head, &len_ptr);
+	ret = get_list(0, &get_head, robust2, 0);
 	ASSERT_EQ(ret, 0);
 	ASSERT_EQ(get_head, &head);
-	ASSERT_EQ(head_size, len_ptr);
 
-	ret = set_robust_list(&head2, head_size);
-	ASSERT_EQ(ret, 0);
+	ret = set_list(&head2, robust2, &index);
+	ASSERT_GE(ret, 0);
 
-	ret = get_robust_list(0, &get_head, &len_ptr);
+	ret = get_list(0, &get_head, robust2, index);
 	ASSERT_EQ(ret, 0);
 	ASSERT_EQ(get_head, &head2);
-	ASSERT_EQ(head_size, len_ptr);
 }
 
+struct child_arg_struct {
+	struct robust_list_head *head;
+	bool robust2;
+};
+
 static int child_list(void *arg)
 {
 	struct child_args *cargs = arg;
 	struct __test_metadata *_metadata = cargs->_metadata;
-	struct robust_list_head *head = cargs->arg;
+	struct child_arg_struct *child_arg = (struct child_arg_struct *) cargs->arg;
+	struct robust_list_head *head = child_arg->head;
+	bool robust2 = child_arg->robust2;
 	int ret;
 
 	free(cargs);
 
-	ret = set_robust_list(head, sizeof(*head));
-	ASSERT_EQ(ret, 0)
+	ret = set_list(head, robust2, 0);
+	ASSERT_GE(ret, 0)
 		TH_LOG("set_robust_list error");
 
 	/*
@@ -507,23 +536,26 @@ static int child_list(void *arg)
  * parent
  *   2) the child thread still alive when we try to get the list from it
  */
-TEST(test_get_robust_list_child)
+TEST_F(robust_api, test_get_robust_list_child)
 {
 	struct robust_list_head head, *get_head;
+	bool robust2 = variant->robust2;
+	struct child_arg_struct child =
+		{.robust2 = robust2, .head = &head};
 	int ret, wstatus;
-	size_t len_ptr;
 	pid_t tid;
 
+
 	ret = pthread_barrier_init(&barrier, NULL, 2);
 	ret = pthread_barrier_init(&barrier2, NULL, 2);
 	ASSERT_EQ(ret, 0);
 
-	tid = create_child(_metadata, &child_list, &head);
+	tid = create_child(_metadata, &child_list, &child);
 	ASSERT_NE(tid, -1);
 
 	pthread_barrier_wait(&barrier);
 
-	ret = get_robust_list(tid, &get_head, &len_ptr);
+	ret = get_list(tid, &get_head, robust2, 0);
 	ASSERT_EQ(ret, 0);
 	ASSERT_EQ(&head, get_head);
 
@@ -1073,9 +1105,9 @@ static int child_lock_holder32(void *arg)
 	struct child_args *cargs = arg;
 	struct lock_struct32 *locks = cargs->arg;
 	struct __test_metadata *_metadata = cargs->_metadata;
-	struct robust_list_head32 *head;
+	struct robust_list_head32 *head, *head_ptr;
 	pid_t tid = gettid();
-	int i, ret;
+	int i, ret, index;
 
 	head = mmap((void *)0x10000, sizeof(*head), PROT_READ | PROT_WRITE,
 		    MAP_FIXED_NOREPLACE | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
@@ -1088,9 +1120,20 @@ static int child_lock_holder32(void *arg)
 	head->list.next = (uint32_t)(uintptr_t) &head->list;
 	head->list_op_pending = (uint32_t)(uintptr_t) NULL;
 
-	ret = set_robust_list2((struct robust_list_head *) head,
+	index = set_robust_list2((struct robust_list_head *)head,
 			FUTEX_ROBUST_LIST_CMD_CREATE_32, 0, 0);
+	ASSERT_GE(index, 0);
+
+	/* Test get list */
+	ret = get_robust_list2(0, (struct robust_list_head **)&head_ptr, index, 0);
 	ASSERT_GE(ret, 0);
+	ASSERT_EQ(head, head_ptr);
+
+	/* Test trying to set a 64 bit list in the same index */
+	ret = set_robust_list2((struct robust_list_head *)head,
+			       FUTEX_ROBUST_LIST_CMD_MODIFY_64, 0, 0);
+	ASSERT_EQ(ret, -1);
+	ASSERT_TRUE(errno & (EOPNOTSUPP | EINVAL));
 
 	/*
 	 * Take all the locks and insert them in the list
@@ -1203,4 +1246,83 @@ TEST(test_32bit_lists)
 	munmap(locks, sizeof(*locks) * CHILD_NR);
 }
 
+/*
+ * Test setting and getting mutiple head lists
+ */
+TEST(set_and_get_robust2)
+{
+	struct robust_list_head *head = NULL, *heads;
+	int list_limit, ret, *index, i, j;
+
+	if (!robust_list2_support()) {
+		SKIP(return, "robust_list2 not supported\n");
+		return;
+	}
+
+	list_limit = set_robust_list2(NULL, FUTEX_ROBUST_LIST_CMD_LIST_LIMIT, 0, 0);
+	ASSERT_GT(list_limit, 1);
+
+	heads = malloc(list_limit * sizeof(*heads));
+	ASSERT_NE(heads, NULL);
+
+	index = malloc(list_limit * sizeof(*index));
+	ASSERT_NE(index, NULL);
+
+	/*
+	 * Insert various elements into the lists
+	 */
+	for (i = 0; i < list_limit; i++) {
+		ret = set_list(&heads[i], true, &index[i]);
+		ASSERT_GE(ret, 0);
+		ASSERT_EQ(i, index[i]);
+	}
+
+	for (i = 0; i < list_limit; i++) {
+		ret = get_list(0, &head, true, index[i]);
+		ASSERT_EQ(ret, 0);
+		ASSERT_EQ(head, &heads[i]);
+	}
+
+	/*
+	 * Modify the list, adding the elements in the other ordering
+	 */
+	for (i = 0, j = list_limit; i < list_limit; i++, j--) {
+		ret = modify_list(&heads[j], index[i]);
+		ASSERT_GE(ret, 0);
+	}
+
+	for (i = 0, j = list_limit; i < list_limit; i++, j--) {
+		ret = get_list(0, &head, true, index[i]);
+		ASSERT_EQ(ret, 0);
+		ASSERT_EQ(head, &heads[j]);
+	}
+
+	/*
+	 * Delete all elements
+	 */
+	for (i = 0; i < list_limit; i++) {
+		ret = modify_list(NULL, index[i]);
+		ASSERT_EQ(ret, 0);
+	}
+
+	for (i = 0; i < list_limit; i++) {
+		ret = get_list(0, &head, true, index[i]);
+		ASSERT_EQ(ret, 0);
+		ASSERT_EQ(head, NULL);
+	}
+
+	/*
+	 * Recreate the list. It should support the same number of elements as
+	 * before, given that we just cleared the list.
+	 */
+	for (i = 0; i < list_limit; i++) {
+		ret = set_list(&heads[i], true, &index[i]);
+		ASSERT_GE(ret, 0);
+		ASSERT_EQ(i, index[i]);
+	}
+
+	free(heads);
+	free(index);
+}
+
 TEST_HARNESS_MAIN

-- 
2.56.1


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

* [PATCH v8 10/10] futex: Use new robust list API internally
  2026-11-15 17:31 [PATCH v8 00/10] futex: Create {set,get}_robust_list2() syscalls André Almeida
                   ` (8 preceding siblings ...)
  2026-11-15 17:31 ` [PATCH v8 09/10] selftests/futex: Expand for get_robust_list2() André Almeida
@ 2026-11-15 17:31 ` André Almeida
  2026-11-15 20:44   ` kernel test robot
  9 siblings, 1 reply; 14+ messages in thread
From: André Almeida @ 2026-11-15 17:31 UTC (permalink / raw)
  To: Ingo Molnar, Peter Zijlstra, Darren Hart, Davidlohr Bueso,
	Arnd Bergmann, Sebastian Andrzej Siewior, Waiman Long,
	Ryan Houdek, Thomas Gleixner
  Cc: linux-kernel, linux-kselftest, linux-api, kernel-dev, André Almeida

The new robust list API internals can handle any kind of robust list, so
to simplify the code, reuse the same mechanisms for the original API and
when calling the original set syscall, set the head in the array of
lists. The first two indexes of the array of robust lists are reserved
for the original API lists, the native robust list and the compat robust
list.

Signed-off-by: André Almeida <andrealmeid@igalia.com>
---
 include/linux/futex.h       |  4 ----
 include/linux/futex_types.h |  6 ------
 kernel/futex/core.c         | 35 +++++++++++++++++--------------
 kernel/futex/syscalls.c     | 50 +++++++++++++++++++++++----------------------
 4 files changed, 46 insertions(+), 49 deletions(-)

diff --git a/include/linux/futex.h b/include/linux/futex.h
index 03a3973a7068..160e7e72b085 100644
--- a/include/linux/futex.h
+++ b/include/linux/futex.h
@@ -95,10 +95,6 @@ static inline void futex_init_task(struct task_struct *tsk)
 	INIT_LIST_HEAD(&tsk->futex.pi_state_list);
 	tsk->futex.state = FUTEX_STATE_OK;
 	mutex_init(&tsk->futex.exit_mutex);
-	tsk->futex.robust_list = NULL;
-#ifdef CONFIG_COMPAT
-	tsk->futex.robust_list32 = NULL;
-#endif
 	tsk->futex.robust_lists = NULL;
 }
 
diff --git a/include/linux/futex_types.h b/include/linux/futex_types.h
index 58321314ecab..45c614923e46 100644
--- a/include/linux/futex_types.h
+++ b/include/linux/futex_types.h
@@ -12,8 +12,6 @@ struct robust_list_head;
 
 /**
  * struct futex_sched_data - Futex related per task data
- * @robust_list:	User space registered robust list pointer
- * @robust_list32:	User space registered robust list pointer for compat tasks
  * @pi_state_list:	List head for Priority Inheritance (PI) state management
  * @pi_state_cache:	Pointer to cache one PI state object per task
  * @exit_mutex:		Mutex for serializing exit
@@ -21,10 +19,6 @@ struct robust_list_head;
  * @robust_lists:	List of robust lists heads
  */
 struct futex_sched_data {
-	struct robust_list_head __user		*robust_list;
-#ifdef CONFIG_COMPAT
-	struct robust_list_head32 __user *robust_list32;
-#endif
 	struct list_head			pi_state_list;
 	struct futex_pi_state			*pi_state_cache;
 	struct mutex				exit_mutex;
diff --git a/kernel/futex/core.c b/kernel/futex/core.c
index dd6fa8035fb6..23880a9d8bac 100644
--- a/kernel/futex/core.c
+++ b/kernel/futex/core.c
@@ -96,6 +96,13 @@ int futex_robust_list_create(uintptr_t head, enum robust_list2_cmd cmd)
 	}
 
 	switch (cmd) {
+	case FUTEX_ROBUST_LIST_SET_COMPAT:
+		entry |= FUTEX_ROBUST_LIST_ENTRY_32BIT;
+		index = FUTEX_ROBUST_LIST_COMPAT_IDX;
+		break;
+	case FUTEX_ROBUST_LIST_SET_NATIVE:
+		index = FUTEX_ROBUST_LIST_NATIVE_IDX;
+		break;
 	case FUTEX_ROBUST_LIST_CMD_CREATE_32:
 		if (head)
 			entry |= FUTEX_ROBUST_LIST_ENTRY_32BIT;
@@ -1294,7 +1301,8 @@ static void exit_robust_list(struct task_struct *curr, struct robust_list_head _
 
 static bool robust_list_clear_pending(unsigned long __user *pop)
 {
-	struct robust_list_head __user *head = current->futex.robust_list;
+	struct robust_list_head __user *head = (struct robust_list_head __user *)
+		current->futex.robust_lists[FUTEX_ROBUST_LIST_NATIVE_IDX];
 
 	if (!put_user(0UL, pop))
 		return true;
@@ -1309,7 +1317,8 @@ static bool robust_list_clear_pending(unsigned long __user *pop)
 	 * that's mostly an academic exercise.
 	 */
 	if (pop == (unsigned long __user *)&head->list_op_pending)
-		current->futex.robust_list = NULL;
+		current->futex.robust_lists[FUTEX_ROBUST_LIST_NATIVE_IDX] = 0;
+
 	return false;
 }
 
@@ -1412,14 +1421,16 @@ static void exit_robust_list32(struct task_struct *curr, struct robust_list_head
 
 static bool robust_list_clear_pending32(u32 __user *pop)
 {
-	struct robust_list_head32 __user *head = current->futex.robust_list32;
+	struct robust_list_head32 __user *head =
+		(struct robust_list_head32 __user *)
+		current->futex.robust_lists[FUTEX_ROBUST_LIST_COMPAT_IDX];
 
 	if (!put_user(0U, pop))
 		return true;
 
 	/* See comment in robust_list_clear_pending(). */
 	if (pop == &head->list_op_pending)
-		current->futex.robust_list32 = NULL;
+		current->futex.robust_lists[FUTEX_ROBUST_LIST_COMPAT_IDX] = 0;
 	return false;
 }
 #else
@@ -1527,6 +1538,9 @@ bool futex_robust_list_clear_pending(void __user *pop, unsigned int flags)
 {
 	bool size32bit = !!(flags & FLAGS_ROBUST_LIST32);
 
+	if (!current->futex.robust_lists)
+		return false;
+
 	if (!IS_ENABLED(CONFIG_64BIT) && !size32bit)
 		return false;
 
@@ -1591,17 +1605,8 @@ static void exit_robust_lists(struct task_struct *tsk)
 
 static void futex_cleanup(struct task_struct *tsk)
 {
-	if (unlikely(tsk->futex.robust_list)) {
-		exit_robust_list(tsk, tsk->futex.robust_list);
-		tsk->futex.robust_list = NULL;
-	}
-
-#ifdef CONFIG_64BIT
-	if (unlikely(tsk->futex.robust_list32)) {
-		exit_robust_list32(tsk, tsk->futex.robust_list32);
-		tsk->futex.robust_list32 = NULL;
-	}
-#endif
+	if (unlikely(tsk->futex.robust_lists))
+		exit_robust_lists(tsk);
 
 	if (unlikely(!list_empty(&tsk->futex.pi_state_list)))
 		exit_pi_state_list(tsk);
diff --git a/kernel/futex/syscalls.c b/kernel/futex/syscalls.c
index 0ecb32afd5e1..ba6730bfd47d 100644
--- a/kernel/futex/syscalls.c
+++ b/kernel/futex/syscalls.c
@@ -27,21 +27,19 @@
  */
 SYSCALL_DEFINE2(set_robust_list, struct robust_list_head __user *, head, size_t, len)
 {
-	/* The kernel knows only one size for now. */
+	int ret;
+
+	/*
+	 * The kernel knows only one size for now:
+	 */
 	if (unlikely(len != sizeof(*head)))
 		return -EINVAL;
 
-	current->futex.robust_list = head;
-	return 0;
-}
-
-static inline void __user *futex_task_robust_list(struct task_struct *p, bool compat)
-{
-#ifdef CONFIG_COMPAT
-	if (compat)
-		return p->futex.robust_list32;
-#endif
-	return p->futex.robust_list;
+	ret = futex_robust_list_create((uintptr_t) head,
+				       FUTEX_ROBUST_LIST_SET_NATIVE);
+	if (ret >= 0)
+		return 0;
+	return ret;
 }
 
 static void __user *futex_get_robust_list_common(int pid, bool compat, int index)
@@ -50,6 +48,9 @@ static void __user *futex_get_robust_list_common(int pid, bool compat, int index
 	void __user *head;
 	int ret;
 
+	if (index >= FUTEX_ROBUST_LIST2_MAX_IDX)
+		return (void __user *)ERR_PTR(-EINVAL);
+
 	scoped_guard(rcu) {
 		if (pid) {
 			p = find_task_by_vpid(pid);
@@ -74,11 +75,8 @@ static void __user *futex_get_robust_list_common(int pid, bool compat, int index
 	if (index >= 0) {
 		scoped_guard(mutex, &p->futex.exit_mutex) {
 			uintptr_t *rl = p->futex.robust_lists;
-
 			head = rl ? (void __user *) rl[index] : NULL;
 		}
-	} else {
-		head = futex_task_robust_list(p, compat);
 	}
 
 	up_read(&p->signal->exec_update_lock);
@@ -103,11 +101,15 @@ SYSCALL_DEFINE3(get_robust_list, int, pid,
 		struct robust_list_head __user * __user *, head_ptr,
 		size_t __user *, len_ptr)
 {
-	struct robust_list_head __user *head = futex_get_robust_list_common(pid, false, -1);
+	struct robust_list_head __user *head =
+		futex_get_robust_list_common(pid, false, FUTEX_ROBUST_LIST_NATIVE_IDX);
 
 	if (IS_ERR(head))
 		return PTR_ERR(head);
 
+	head = (struct robust_list_head __user *)
+		((uintptr_t) head & FUTEX_ROBUST_LIST_ENTRY_MASK);
+
 	if (put_user(sizeof(*head), len_ptr))
 		return -EFAULT;
 	return put_user(head, head_ptr);
@@ -168,8 +170,7 @@ SYSCALL_DEFINE4(set_robust_list2, struct robust_list_head * __user, head, unsign
 	return -EINVAL;
 }
 
-SYSCALL_DEFINE4(get_robust_list2, int, pid,
-		void __user * __user *, head_ptr,
+SYSCALL_DEFINE4(get_robust_list2, int, pid, void __user * __user *, head_ptr,
 		unsigned int, index, unsigned int, flags)
 {
 	struct robust_list_head *head;
@@ -597,22 +598,23 @@ COMPAT_SYSCALL_DEFINE2(set_robust_list, struct robust_list_head32 __user *, head
 	if (unlikely(len != sizeof(*head)))
 		return -EINVAL;
 
-	current->futex.robust_list32 = head;
-
-	return 0;
+	return futex_robust_list_create((uintptr_t) head,
+					FUTEX_ROBUST_LIST_SET_COMPAT);
 }
 
 COMPAT_SYSCALL_DEFINE3(get_robust_list, int, pid,
 			compat_uptr_t __user *, head_ptr,
 			compat_size_t __user *, len_ptr)
 {
-	struct robust_list_head32 __user *head = futex_get_robust_list_common(pid, true, -1);
+	struct robust_list_head32 __user *head =
+		futex_get_robust_list_common(pid, true, FUTEX_ROBUST_LIST_COMPAT_IDX);
 
-	if (IS_ERR(head))
-		return PTR_ERR(head);
+	head = (struct robust_list_head32 __user *)
+		((uintptr_t) head & FUTEX_ROBUST_LIST_ENTRY_MASK);
 
 	if (put_user(sizeof(*head), len_ptr))
 		return -EFAULT;
+
 	return put_user(ptr_to_compat(head), head_ptr);
 }
 #endif /* CONFIG_COMPAT */

-- 
2.56.1


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

* Re: [PATCH v8 10/10] futex: Use new robust list API internally
  2026-11-15 17:31 ` [PATCH v8 10/10] futex: Use new robust list API internally André Almeida
@ 2026-11-15 20:44   ` kernel test robot
  0 siblings, 0 replies; 14+ messages in thread
From: kernel test robot @ 2026-11-15 20:44 UTC (permalink / raw)
  To: André Almeida, Ingo Molnar, Peter Zijlstra, Darren Hart,
	Davidlohr Bueso, Arnd Bergmann, Sebastian Andrzej Siewior,
	Waiman Long, Ryan Houdek, Thomas Gleixner
  Cc: llvm, oe-kbuild-all, linux-kernel, linux-kselftest, linux-api,
	kernel-dev, André Almeida

Hi André,

kernel test robot noticed the following build warnings:

[auto build test WARNING on 9f74092fda91ef93c2b07585785c1dc83cd7971f]

url:    https://github.com/intel-lab-lkp/linux/commits/Andr-Almeida/futex-Skip-test_futex_robust_unlock-if-not-supported/20261115-143110
base:   9f74092fda91ef93c2b07585785c1dc83cd7971f
patch link:    https://lore.kernel.org/r/20261115-tonyk-robust_futex-v8-10-a4fe47333a28%40igalia.com
patch subject: [PATCH v8 10/10] futex: Use new robust list API internally
config: x86_64-allnoconfig (https://download.01.org/0day-ci/archive/20261116/202611160419.vIdH20Tu-lkp@intel.com/config)
compiler: clang version 22.1.8 (https://github.com/llvm/llvm-project ca7933e47d3a3451d81e72ac174dcb5aa28b59d1)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20261116/202611160419.vIdH20Tu-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202611160419.vIdH20Tu-lkp@intel.com/

All warnings (new ones prefixed by >>):

>> kernel/futex/syscalls.c:75:6: warning: variable 'head' is used uninitialized whenever 'if' condition is false [-Wsometimes-uninitialized]
      75 |         if (index >= 0) {
         |             ^~~~~~~~~~
   kernel/futex/syscalls.c:85:9: note: uninitialized use occurs here
      85 |         return head;
         |                ^~~~
   kernel/futex/syscalls.c:75:2: note: remove the 'if' if its condition is always true
      75 |         if (index >= 0) {
         |         ^~~~~~~~~~~~~~~
   kernel/futex/syscalls.c:48:19: note: initialize the variable 'head' to silence this warning
      48 |         void __user *head;
         |                          ^
         |                           = NULL
   1 warning generated.


vim +75 kernel/futex/syscalls.c

af8cc9600bbf22 Peter Zijlstra 2021-09-23  44  
5588aabbe40841 André Almeida  2026-11-15  45  static void __user *futex_get_robust_list_common(int pid, bool compat, int index)
6b54082c3ed4dc Pranav Tyagi   2025-09-15  46  {
6b54082c3ed4dc Pranav Tyagi   2025-09-15  47  	struct task_struct *p = current;
6b54082c3ed4dc Pranav Tyagi   2025-09-15  48  	void __user *head;
6b54082c3ed4dc Pranav Tyagi   2025-09-15  49  	int ret;
af8cc9600bbf22 Peter Zijlstra 2021-09-23  50  
a2d2b7acb53d36 André Almeida  2026-11-15  51  	if (index >= FUTEX_ROBUST_LIST2_MAX_IDX)
a2d2b7acb53d36 André Almeida  2026-11-15  52  		return (void __user *)ERR_PTR(-EINVAL);
a2d2b7acb53d36 André Almeida  2026-11-15  53  
6b54082c3ed4dc Pranav Tyagi   2025-09-15  54  	scoped_guard(rcu) {
6b54082c3ed4dc Pranav Tyagi   2025-09-15  55  		if (pid) {
af8cc9600bbf22 Peter Zijlstra 2021-09-23  56  			p = find_task_by_vpid(pid);
af8cc9600bbf22 Peter Zijlstra 2021-09-23  57  			if (!p)
6b54082c3ed4dc Pranav Tyagi   2025-09-15  58  				return (void __user *)ERR_PTR(-ESRCH);
6b54082c3ed4dc Pranav Tyagi   2025-09-15  59  		}
6b54082c3ed4dc Pranav Tyagi   2025-09-15  60  		get_task_struct(p);
af8cc9600bbf22 Peter Zijlstra 2021-09-23  61  	}
af8cc9600bbf22 Peter Zijlstra 2021-09-23  62  
6b54082c3ed4dc Pranav Tyagi   2025-09-15  63  	/*
6b54082c3ed4dc Pranav Tyagi   2025-09-15  64  	 * Hold exec_update_lock to serialize with concurrent exec()
6b54082c3ed4dc Pranav Tyagi   2025-09-15  65  	 * so ptrace_may_access() is checked against stable credentials
6b54082c3ed4dc Pranav Tyagi   2025-09-15  66  	 */
6b54082c3ed4dc Pranav Tyagi   2025-09-15  67  	ret = down_read_killable(&p->signal->exec_update_lock);
6b54082c3ed4dc Pranav Tyagi   2025-09-15  68  	if (ret)
6b54082c3ed4dc Pranav Tyagi   2025-09-15  69  		goto err_put;
6b54082c3ed4dc Pranav Tyagi   2025-09-15  70  
af8cc9600bbf22 Peter Zijlstra 2021-09-23  71  	ret = -EPERM;
af8cc9600bbf22 Peter Zijlstra 2021-09-23  72  	if (!ptrace_may_access(p, PTRACE_MODE_READ_REALCREDS))
af8cc9600bbf22 Peter Zijlstra 2021-09-23  73  		goto err_unlock;
af8cc9600bbf22 Peter Zijlstra 2021-09-23  74  
5588aabbe40841 André Almeida  2026-11-15 @75  	if (index >= 0) {
5588aabbe40841 André Almeida  2026-11-15  76  		scoped_guard(mutex, &p->futex.exit_mutex) {
5588aabbe40841 André Almeida  2026-11-15  77  			uintptr_t *rl = p->futex.robust_lists;
5588aabbe40841 André Almeida  2026-11-15  78  			head = rl ? (void __user *) rl[index] : NULL;
5588aabbe40841 André Almeida  2026-11-15  79  		}
5588aabbe40841 André Almeida  2026-11-15  80  	}
af8cc9600bbf22 Peter Zijlstra 2021-09-23  81  
6b54082c3ed4dc Pranav Tyagi   2025-09-15  82  	up_read(&p->signal->exec_update_lock);
6b54082c3ed4dc Pranav Tyagi   2025-09-15  83  	put_task_struct(p);
6b54082c3ed4dc Pranav Tyagi   2025-09-15  84  
6b54082c3ed4dc Pranav Tyagi   2025-09-15  85  	return head;
af8cc9600bbf22 Peter Zijlstra 2021-09-23  86  
af8cc9600bbf22 Peter Zijlstra 2021-09-23  87  err_unlock:
6b54082c3ed4dc Pranav Tyagi   2025-09-15  88  	up_read(&p->signal->exec_update_lock);
6b54082c3ed4dc Pranav Tyagi   2025-09-15  89  err_put:
6b54082c3ed4dc Pranav Tyagi   2025-09-15  90  	put_task_struct(p);
6b54082c3ed4dc Pranav Tyagi   2025-09-15  91  	return (void __user *)ERR_PTR(ret);
6b54082c3ed4dc Pranav Tyagi   2025-09-15  92  }
af8cc9600bbf22 Peter Zijlstra 2021-09-23  93  

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

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

* Re: [PATCH v8 06/10] futex: Wire up set_robust_list2 syscall
  2026-11-15 17:31 ` [PATCH v8 06/10] futex: Wire up set_robust_list2 syscall André Almeida
@ 2026-11-15 20:55   ` kernel test robot
  2026-11-15 21:30   ` kernel test robot
  1 sibling, 0 replies; 14+ messages in thread
From: kernel test robot @ 2026-11-15 20:55 UTC (permalink / raw)
  To: André Almeida, Ingo Molnar, Peter Zijlstra, Darren Hart,
	Davidlohr Bueso, Arnd Bergmann, Sebastian Andrzej Siewior,
	Waiman Long, Ryan Houdek, Thomas Gleixner
  Cc: oe-kbuild-all, linux-kernel, linux-kselftest, linux-api,
	kernel-dev, André Almeida

Hi André,

kernel test robot noticed the following build errors:

[auto build test ERROR on 9f74092fda91ef93c2b07585785c1dc83cd7971f]

url:    https://github.com/intel-lab-lkp/linux/commits/Andr-Almeida/futex-Skip-test_futex_robust_unlock-if-not-supported/20261115-143110
base:   9f74092fda91ef93c2b07585785c1dc83cd7971f
patch link:    https://lore.kernel.org/r/20261115-tonyk-robust_futex-v8-6-a4fe47333a28%40igalia.com
patch subject: [PATCH v8 06/10] futex: Wire up set_robust_list2 syscall
config: openrisc-allnoconfig (https://download.01.org/0day-ci/archive/20261116/202611160433.ySzwblT6-lkp@intel.com/config)
compiler: or1k-linux-gcc (GCC) 16.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20261116/202611160433.ySzwblT6-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202611160433.ySzwblT6-lkp@intel.com/

All errors (new ones prefixed by >>):

>> ./arch/openrisc/include/generated/asm/syscall_table_32.h:474:16: error: 'sys_set_robust_list2' undeclared here (not in a function); did you mean 'sys_set_robust_list'?
     474 | __SYSCALL(473, sys_set_robust_list2)
         |                ^~~~~~~~~~~~~~~~~~~~
   arch/openrisc/kernel/sys_call_table.c:19:37: note: in definition of macro '__SYSCALL'
      19 | #define __SYSCALL(nr, call) [nr] = (call),
         |                                     ^~~~

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

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

* Re: [PATCH v8 06/10] futex: Wire up set_robust_list2 syscall
  2026-11-15 17:31 ` [PATCH v8 06/10] futex: Wire up set_robust_list2 syscall André Almeida
  2026-11-15 20:55   ` kernel test robot
@ 2026-11-15 21:30   ` kernel test robot
  1 sibling, 0 replies; 14+ messages in thread
From: kernel test robot @ 2026-11-15 21:30 UTC (permalink / raw)
  To: André Almeida, Ingo Molnar, Peter Zijlstra, Darren Hart,
	Davidlohr Bueso, Arnd Bergmann, Sebastian Andrzej Siewior,
	Waiman Long, Ryan Houdek, Thomas Gleixner
  Cc: oe-kbuild-all, linux-kernel, linux-kselftest, linux-api,
	kernel-dev, André Almeida

Hi André,

kernel test robot noticed the following build errors:

[auto build test ERROR on 9f74092fda91ef93c2b07585785c1dc83cd7971f]

url:    https://github.com/intel-lab-lkp/linux/commits/Andr-Almeida/futex-Skip-test_futex_robust_unlock-if-not-supported/20261115-143110
base:   9f74092fda91ef93c2b07585785c1dc83cd7971f
patch link:    https://lore.kernel.org/r/20261115-tonyk-robust_futex-v8-6-a4fe47333a28%40igalia.com
patch subject: [PATCH v8 06/10] futex: Wire up set_robust_list2 syscall
config: xtensa-allnoconfig (https://download.01.org/0day-ci/archive/20261116/202611160554.MGBENVam-lkp@intel.com/config)
compiler: xtensa-linux-gcc (GCC) 16.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20261116/202611160554.MGBENVam-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202611160554.MGBENVam-lkp@intel.com/

All errors (new ones prefixed by >>):

>> ./arch/xtensa/include/generated/asm/syscall_table.h:474:16: error: 'sys_set_robust_list2' undeclared here (not in a function); did you mean 'sys_set_robust_list'?
     474 | __SYSCALL(473, sys_set_robust_list2)
         |                ^~~~~~~~~~~~~~~~~~~~
   arch/xtensa/kernel/syscall.c:31:44: note: in definition of macro '__SYSCALL'
      31 | #define __SYSCALL(nr, entry)    (syscall_t)entry,
         |                                            ^~~~~

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

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

end of thread, other threads:[~2026-11-15 21:31 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-11-15 17:31 [PATCH v8 00/10] futex: Create {set,get}_robust_list2() syscalls André Almeida
2026-11-15 17:31 ` [PATCH v8 01/10] futex: Skip test_futex_robust_unlock() if not supported André Almeida
2026-11-15 17:31 ` [PATCH v8 02/10] futex: Use explicit sizes for compat_robust_list structs André Almeida
2026-11-15 17:31 ` [PATCH v8 03/10] futex: Make exit_robust_list32() unconditionally available for 64-bit kernels André Almeida
2026-11-15 17:31 ` [PATCH v8 04/10] futex: Create set_robust_list2() syscall André Almeida
2026-11-15 17:31 ` [PATCH v8 05/10] futex: Create get_robust_list2() syscall André Almeida
2026-11-15 17:31 ` [PATCH v8 06/10] futex: Wire up set_robust_list2 syscall André Almeida
2026-11-15 20:55   ` kernel test robot
2026-11-15 21:30   ` kernel test robot
2026-11-15 17:31 ` [PATCH v8 07/10] futex: Wire up get_robust_list2 syscall André Almeida
2026-11-15 17:31 ` [PATCH v8 08/10] selftests/futex: Expand for set_robust_list2() André Almeida
2026-11-15 17:31 ` [PATCH v8 09/10] selftests/futex: Expand for get_robust_list2() André Almeida
2026-11-15 17:31 ` [PATCH v8 10/10] futex: Use new robust list API internally André Almeida
2026-11-15 20:44   ` kernel test robot

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®