From nobody Tue Dec 2 01:08:01 2025 Received: from fanzine2.igalia.com (fanzine2.igalia.com [213.97.179.56]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 71BC827472; Sat, 22 Nov 2025 05:51:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=213.97.179.56 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763790678; cv=none; b=lWoKiK+7WvD2Wa/Ze3fEiGoFquz1wHvBa4lC9PxFScsxTO91QXl/Qx3LGA4giinYS2vnIVixsVCS2bCPEnOUINxt+c9YLLLPX+LWaW8T3xf+tWRgH87HSX/Y6RfEl7gW8DCAHX7b9KtcDX8w2UlzXkd1C3U0OQWtQud2DklM1SE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763790678; c=relaxed/simple; bh=a5e0WtmE31hjyJgzIO30tYa+3yYEus9iohkBFUET4TM=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=RWvDfKJdgIOScnSWzgJw8mbDg61y6YK0C0LBIy9VYpYLvNLwZADuDzyrO394rTvnprcI18O/sE7w8FKJyv7RC4bF+wBgv9dQ/YN6UO6bNp2MauBsaxzbcdoAFvk2HTbLZpAOG6m6IrErN576oPoAXQWpHuXXq8bdP5Q5eKlM+rU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=igalia.com; spf=pass smtp.mailfrom=igalia.com; dkim=pass (2048-bit key) header.d=igalia.com header.i=@igalia.com header.b=NnEnLTar; arc=none smtp.client-ip=213.97.179.56 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=igalia.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=igalia.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=igalia.com header.i=@igalia.com header.b="NnEnLTar" DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=igalia.com; s=20170329; h=Cc:To:In-Reply-To:References:Message-Id: Content-Transfer-Encoding:Content-Type:MIME-Version:Subject:Date:From:Sender: Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender :Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=AnwA/qmj6OsksCBaVbOLbdcJ5EzsvrOTwevQOw/XH3U=; b=NnEnLTarqdBzDJi0nODi4YraZr G7bp0R8ESu5YQ7mpoMx10jddeS1L9ZaiFZnsHwSH/5+yh7VAtrT/AtmkBrfO3nGcwDpN90CdTsfAt XsZYVMvkEVdDbwzhJN0cx8KhTOJMOj0drme3mHRbbQ89KdP0FM5xe49AWOChJCYgXCODNRtbc+vT4 eSjTDqEHhcyAnYPKb2z/z8rQ24HB6N5XXwabY/lP4NsiqQPaJBg0aPlrhj0UXLmoy6Sym7Skw1h98 +ewieIgynNLafzHT9Zcy6ZIYnCmuFTVJ7WDKU4qjYfOac3ka61O0ii/kNzsCAZE9GNGTC3Utsv8vf LlY8jURw==; Received: from [187.101.0.152] (helo=[192.168.15.100]) by fanzine2.igalia.com with esmtpsa (Cipher TLS1.3:ECDHE_X25519__RSA_PSS_RSAE_SHA256__AES_256_GCM:256) (Exim) id 1vMgWc-003xEt-Dq; Sat, 22 Nov 2025 06:51:10 +0100 From: =?utf-8?q?Andr=C3=A9_Almeida?= Date: Sat, 22 Nov 2025 02:50:43 -0300 Subject: [PATCH v6 1/9] futex: Use explicit sizes for compat_robust_list structs Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251122-tonyk-robust_futex-v6-1-05fea005a0fd@igalia.com> References: <20251122-tonyk-robust_futex-v6-0-05fea005a0fd@igalia.com> In-Reply-To: <20251122-tonyk-robust_futex-v6-0-05fea005a0fd@igalia.com> To: Thomas Gleixner , Ingo Molnar , Peter Zijlstra , Darren Hart , Davidlohr Bueso , Arnd Bergmann , Sebastian Andrzej Siewior , Waiman Long , Ryan Houdek Cc: linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-api@vger.kernel.org, kernel-dev@igalia.com, =?utf-8?q?Andr=C3=A9_Almeida?= X-Mailer: b4 0.14.3 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=C3=A9 Almeida --- include/linux/compat.h | 13 +++---------- include/linux/futex.h | 2 +- include/linux/sched.h | 2 +- include/uapi/linux/futex.h | 10 ++++++++++ kernel/futex/core.c | 20 ++++++++++---------- kernel/futex/syscalls.c | 8 ++++---- 6 files changed, 29 insertions(+), 26 deletions(-) diff --git a/include/linux/compat.h b/include/linux/compat.h index 56cebaff0c91..2c5a7f980182 100644 --- a/include/linux/compat.h +++ b/include/linux/compat.h @@ -385,15 +385,8 @@ struct compat_ifconf { compat_caddr_t ifcbuf; }; =20 -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; =20 #ifdef CONFIG_COMPAT_OLD_SIGACTION struct compat_old_sigaction { @@ -672,7 +665,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 9e9750f04980..322851e4a703 100644 --- a/include/linux/futex.h +++ b/include/linux/futex.h @@ -66,7 +66,7 @@ static inline void futex_init_task(struct task_struct *ts= k) { tsk->robust_list =3D NULL; #ifdef CONFIG_COMPAT - tsk->compat_robust_list =3D NULL; + tsk->robust_list32 =3D NULL; #endif INIT_LIST_HEAD(&tsk->pi_state_list); tsk->pi_state_cache =3D NULL; diff --git a/include/linux/sched.h b/include/linux/sched.h index cbb7340c5866..76cabfab5b73 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -1332,7 +1332,7 @@ struct task_struct { #ifdef CONFIG_FUTEX 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 7e2744ec8933..86efb089893d 100644 --- a/include/uapi/linux/futex.h +++ b/include/uapi/linux/futex.h @@ -153,6 +153,16 @@ struct robust_list_head { struct robust_list __user *list_op_pending; }; =20 +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 125804fbb5cb..c99d7baab24e 100644 --- a/kernel/futex/core.c +++ b/kernel/futex/core.c @@ -1227,7 +1227,7 @@ 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, +fetch_robust_entry32(compat_uptr_t *uentry, struct robust_list __user **en= try, compat_uptr_t __user *head, unsigned int *pi) { if (get_user(*uentry, head)) @@ -1245,9 +1245,9 @@ compat_fetch_robust_entry(compat_uptr_t *uentry, stru= ct 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 =3D curr->compat_robust_list; + struct robust_list_head32 __user *head =3D curr->robust_list32; struct robust_list __user *entry, *next_entry, *pending; unsigned int limit =3D ROBUST_LIST_LIMIT, pi, pip; unsigned int next_pi; @@ -1259,7 +1259,7 @@ static void compat_exit_robust_list(struct task_struc= t *curr) * Fetch the list head (which was registered earlier, via * sys_set_robust_list()): */ - if (compat_fetch_robust_entry(&uentry, &entry, &head->list.next, &pi)) + if (fetch_robust_entry32(&uentry, &entry, &head->list.next, &pi)) return; /* * Fetch the relative futex offset: @@ -1270,7 +1270,7 @@ static void compat_exit_robust_list(struct task_struc= t *curr) * Fetch any possibly pending lock-add first, and handle it * if it exists: */ - if (compat_fetch_robust_entry(&upending, &pending, + if (fetch_robust_entry32(&upending, &pending, &head->list_op_pending, &pip)) return; =20 @@ -1280,8 +1280,8 @@ static void compat_exit_robust_list(struct task_struc= t *curr) * Fetch the next entry in the list before calling * handle_futex_death: */ - rc =3D compat_fetch_robust_entry(&next_uentry, &next_entry, - (compat_uptr_t __user *)&entry->next, &next_pi); + rc =3D fetch_robust_entry32(&next_uentry, &next_entry, + (u32 __user *)&entry->next, &next_pi); /* * A pending lock might already be on the list, so * dont process it twice: @@ -1413,9 +1413,9 @@ static void futex_cleanup(struct task_struct *tsk) } =20 #ifdef CONFIG_COMPAT - if (unlikely(tsk->compat_robust_list)) { - compat_exit_robust_list(tsk); - tsk->compat_robust_list =3D NULL; + if (unlikely(tsk->robust_list32)) { + exit_robust_list32(tsk); + tsk->robust_list32 =3D NULL; } #endif =20 diff --git a/kernel/futex/syscalls.c b/kernel/futex/syscalls.c index 880c9bf2f315..1de8ff230d54 100644 --- a/kernel/futex/syscalls.c +++ b/kernel/futex/syscalls.c @@ -43,7 +43,7 @@ static inline void __user *futex_task_robust_list(struct = task_struct *p, bool co { #ifdef CONFIG_COMPAT if (compat) - return p->compat_robust_list; + return p->robust_list32; #endif return p->robust_list; } @@ -468,13 +468,13 @@ SYSCALL_DEFINE4(futex_requeue, =20 #ifdef CONFIG_COMPAT COMPAT_SYSCALL_DEFINE2(set_robust_list, - struct compat_robust_list_head __user *, head, + struct robust_list_head32 __user *, head, compat_size_t, len) { if (unlikely(len !=3D sizeof(*head))) return -EINVAL; =20 - current->compat_robust_list =3D head; + current->robust_list32 =3D head; =20 return 0; } @@ -483,7 +483,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 =3D futex_get_robust_list_com= mon(pid, true); + struct robust_list_head32 __user *head =3D futex_get_robust_list_common(p= id, true); =20 if (IS_ERR(head)) return PTR_ERR(head); --=20 2.52.0 From nobody Tue Dec 2 01:08:01 2025 Received: from fanzine2.igalia.com (fanzine2.igalia.com [213.97.179.56]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id F074123A9A8; Sat, 22 Nov 2025 05:51:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=213.97.179.56 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763790680; cv=none; b=sRfC9wxmQZCBciDki/RYcRFZRe18bPu64cpn0J338RrF0adKl5nZ4/NJHsQQsAu1Tp1xU1xq7LwOC4004YCh0ZtayXwqjDcFMOEUSBTuFZUJ/Gy03n7PIG+37Ik+JBj30b3HFtJUpaqHNC49KDHVjZJA6HoiHhE3tPtzB56fo5I= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763790680; c=relaxed/simple; bh=/ZDJnQBlGNOSO0UEqHe5ew7N8SJnqbveSgGLUNHalYs=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=hnc5v0UJM4RNS+Jr6LGd8OshzqwP+21E2aNHIkUxbqXWCSYQ2dwqNCNbVO8DVxH4da3dHb0ZVvYAA0XxmVQJOH5qXG0mzDzPhxF/llAUhFdCr8p1vASjylc5PpLF/CbL278+zyaW/Q5WwteyE1KwCxpooidrz3ZAdEmVwkxKwdc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=igalia.com; spf=pass smtp.mailfrom=igalia.com; dkim=pass (2048-bit key) header.d=igalia.com header.i=@igalia.com header.b=lcdsX+19; arc=none smtp.client-ip=213.97.179.56 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=igalia.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=igalia.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=igalia.com header.i=@igalia.com header.b="lcdsX+19" DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=igalia.com; s=20170329; h=Cc:To:In-Reply-To:References:Message-Id: Content-Transfer-Encoding:Content-Type:MIME-Version:Subject:Date:From:Sender: Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender :Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=GCIZbuTzPUqv8cOo26+OQpOYWfjT0BoJo6GaN8MM1i4=; b=lcdsX+19wsoj62dMx3773Pa7Pi mSFGS+JTRZ/10FW/T5WouKKsDcM4fON/X620huoSSoe2LpJoftx8/PuE6sEeFsDZvLhEKDllfj32I JZdBYzVlFAAN7L+85J4MIqXjigUQHiobXhq6pG0K0RQMmKWhhFAnR/qyGC7t8+b5nO2FYKAEvaYBg iPnlQjKPrYkrquw+z0gKuI1Wl/wb4oEiDccVPGR9sdoaHuGbbHI9lvBGUDDRM1z6zkvLbkdwjSkWy 1ovsSs8uw4McA5bxRLrlwrBmBXbpEGXv5BPxow45Th3zdYi7SMo/NT/SZCLM8Doju+fAKXvNcIOXv RH7WZmlw==; Received: from [187.101.0.152] (helo=[192.168.15.100]) by fanzine2.igalia.com with esmtpsa (Cipher TLS1.3:ECDHE_X25519__RSA_PSS_RSAE_SHA256__AES_256_GCM:256) (Exim) id 1vMgWf-003xEt-Jf; Sat, 22 Nov 2025 06:51:13 +0100 From: =?utf-8?q?Andr=C3=A9_Almeida?= Date: Sat, 22 Nov 2025 02:50:44 -0300 Subject: [PATCH v6 2/9] futex: Make exit_robust_list32() unconditionally available for 64-bit kernels Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251122-tonyk-robust_futex-v6-2-05fea005a0fd@igalia.com> References: <20251122-tonyk-robust_futex-v6-0-05fea005a0fd@igalia.com> In-Reply-To: <20251122-tonyk-robust_futex-v6-0-05fea005a0fd@igalia.com> To: Thomas Gleixner , Ingo Molnar , Peter Zijlstra , Darren Hart , Davidlohr Bueso , Arnd Bergmann , Sebastian Andrzej Siewior , Waiman Long , Ryan Houdek Cc: linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-api@vger.kernel.org, kernel-dev@igalia.com, =?utf-8?q?Andr=C3=A9_Almeida?= X-Mailer: b4 0.14.3 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=C3=A9 Almeida --- kernel/futex/core.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/kernel/futex/core.c b/kernel/futex/core.c index c99d7baab24e..136639897ff9 100644 --- a/kernel/futex/core.c +++ b/kernel/futex/core.c @@ -31,7 +31,6 @@ * "The futexes are also cursed." * "But they come in a choice of three flavours!" */ -#include #include #include #include @@ -1213,12 +1212,12 @@ static void exit_robust_list(struct task_struct *cu= rr) } } =20 -#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 =3D ptr_to_compat(entry); - void __user *uaddr =3D compat_ptr(base + futex_offset); + u32 base =3D (u32)(unsigned long)(entry); + void __user *uaddr =3D (void __user *)(unsigned long)(base + futex_offset= ); =20 return uaddr; } @@ -1227,13 +1226,13 @@ static void __user *futex_uaddr(struct robust_list = __user *entry, * Fetch a robust-list pointer. Bit 0 signals PI futexes: */ static inline int -fetch_robust_entry32(compat_uptr_t *uentry, struct robust_list __user **en= try, - compat_uptr_t __user *head, unsigned int *pi) +fetch_robust_entry32(u32 *uentry, struct robust_list __user **entry, + u32 __user *head, unsigned int *pi) { if (get_user(*uentry, head)) return -EFAULT; =20 - *entry =3D compat_ptr((*uentry) & ~1); + *entry =3D (void __user *)(unsigned long)((*uentry) & ~1); *pi =3D (unsigned int)(*uentry) & 1; =20 return 0; @@ -1251,8 +1250,8 @@ static void exit_robust_list32(struct task_struct *cu= rr) struct robust_list __user *entry, *next_entry, *pending; unsigned int limit =3D ROBUST_LIST_LIMIT, pi, pip; unsigned int next_pi; - compat_uptr_t uentry, next_uentry, upending; - compat_long_t futex_offset; + u32 uentry, next_uentry, upending; + s32 futex_offset; int rc; =20 /* @@ -1412,7 +1411,7 @@ static void futex_cleanup(struct task_struct *tsk) tsk->robust_list =3D NULL; } =20 -#ifdef CONFIG_COMPAT +#ifdef CONFIG_64BIT if (unlikely(tsk->robust_list32)) { exit_robust_list32(tsk); tsk->robust_list32 =3D NULL; --=20 2.52.0 From nobody Tue Dec 2 01:08:01 2025 Received: from fanzine2.igalia.com (fanzine2.igalia.com [213.97.179.56]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7D1922BF001; Sat, 22 Nov 2025 05:51:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=213.97.179.56 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763790684; cv=none; b=NDetO6UjI7OB+HtZFbC71V6SotOSFHarDitqYUkTYZ93yWtmTfd75mLEbT7n+Wq3++boAnwg30HK0ouImGMUerHZ6BShqztypCdhtUQ1Sigz5I2NCtU40aNiR+/aqGJXKtRsBqV1C5JhGJ8jrqmeycUbD6JApDqKfsPuskeKeRA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763790684; c=relaxed/simple; bh=gzn9/EkgVxiA3KJ0mSY4H8pHvFxv0hklj1GOC8fNUHQ=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=dI5Orvs8aOW31QdD+9jtK57656E6NU89pINobDA4gbyT4w0kVjit4WH/ONwjSra8xTnFmZHBTIGm+jeCqntUDeJSN1Mr3hkivIAyj8SL8/3GpOQMWo7RYvNlUhAXtALS727YqRV9dIJhT5Mw5j73G5nvkW9jiT1++CQjg16/TVs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=igalia.com; spf=pass smtp.mailfrom=igalia.com; dkim=pass (2048-bit key) header.d=igalia.com header.i=@igalia.com header.b=VeTFDVhm; arc=none smtp.client-ip=213.97.179.56 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=igalia.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=igalia.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=igalia.com header.i=@igalia.com header.b="VeTFDVhm" DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=igalia.com; s=20170329; h=Cc:To:In-Reply-To:References:Message-Id: Content-Transfer-Encoding:Content-Type:MIME-Version:Subject:Date:From:Sender: Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender :Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=Riw0dCVlXYIc0c55x20LABMFyn6l9sW+SJ5HW68HaAU=; b=VeTFDVhmgcc+gTsb6OmVjIQhp+ xuqHqlmjFiy/13SiWa/B+zf/MdjN3ViH4Gl3JLbdv12l07dhE3o/KTwX1vOoSrQvNKb2SKIGX5PpR WybMJRcT9QzTTmX9dIA5eazrJpPgo/k56Vb89N9gd9yBEGdzEWw8Yf/jiB/3h/5a/xhUPIX3Hngfl 5A0aQl4r6hPTK6C+A1jH5X7H90ooXVn6vThtVDuGPwh2U8g1e1Y7DDu5mAkkh1tjnM1Yyv7p9wzT2 xoWYqLQ5TQHhq0LLptlzIzk+celaerk0HHsD7OjpW21kzEpZQCYyCUa4aSS94QswwJfp5n1WvBOSw ShdKeCVw==; Received: from [187.101.0.152] (helo=[192.168.15.100]) by fanzine2.igalia.com with esmtpsa (Cipher TLS1.3:ECDHE_X25519__RSA_PSS_RSAE_SHA256__AES_256_GCM:256) (Exim) id 1vMgWi-003xEt-Pe; Sat, 22 Nov 2025 06:51:16 +0100 From: =?utf-8?q?Andr=C3=A9_Almeida?= Date: Sat, 22 Nov 2025 02:50:45 -0300 Subject: [PATCH v6 3/9] futex: Create set_robust_list2() syscall Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251122-tonyk-robust_futex-v6-3-05fea005a0fd@igalia.com> References: <20251122-tonyk-robust_futex-v6-0-05fea005a0fd@igalia.com> In-Reply-To: <20251122-tonyk-robust_futex-v6-0-05fea005a0fd@igalia.com> To: Thomas Gleixner , Ingo Molnar , Peter Zijlstra , Darren Hart , Davidlohr Bueso , Arnd Bergmann , Sebastian Andrzej Siewior , Waiman Long , Ryan Houdek Cc: linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-api@vger.kernel.org, kernel-dev@igalia.com, =?utf-8?q?Andr=C3=A9_Almeida?= X-Mailer: b4 0.14.3 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 index, 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. - `index` is the index of the list to be set with `head`. - `cmd` defines the operation to perform: - `FUTEX_ROBUST_LIST_CMD_SET_64` set a 64-bit robust list at `index` - `FUTEX_ROBUST_LIST_CMD_SET_32` set a 32-bit robust list at `index` - `FUTEX_ROBUST_LIST_CMD_LIST_LIMIT` get the limit of lists per task - `flag` is unused now but can be used to expand the interface Setting an index twice overwrites the last instance. 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_SET_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=C3=A9 Almeida --- include/linux/futex.h | 26 +++++++++++ include/linux/sched.h | 1 + include/uapi/linux/futex.h | 16 +++++++ kernel/futex/core.c | 111 +++++++++++++++++++++++++++++++++++++++++= +--- kernel/futex/syscalls.c | 41 +++++++++++++++++ 5 files changed, 188 insertions(+), 7 deletions(-) diff --git a/include/linux/futex.h b/include/linux/futex.h index 322851e4a703..3dba249bcd32 100644 --- a/include/linux/futex.h +++ b/include/linux/futex.h @@ -5,6 +5,7 @@ #include #include #include +#include =20 #include =20 @@ -62,12 +63,35 @@ enum { FUTEX_STATE_DEAD, }; =20 +#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) { tsk->robust_list =3D NULL; #ifdef CONFIG_COMPAT tsk->robust_list32 =3D NULL; #endif + tsk->futex_robust_lists =3D NULL; INIT_LIST_HEAD(&tsk->pi_state_list); tsk->pi_state_cache =3D NULL; tsk->futex_state =3D FUTEX_STATE_OK; @@ -82,6 +106,8 @@ long do_futex(u32 __user *uaddr, int op, u32 val, ktime_= t *timeout, u32 __user *uaddr2, u32 val2, u32 val3); int futex_hash_prctl(unsigned long arg2, unsigned long arg3, unsigned long= arg4); =20 +int futex_robust_list_set(uintptr_t head, enum robust_list2_cmd cmd, unsig= ned int index); + #ifdef CONFIG_FUTEX_PRIVATE_HASH int futex_hash_allocate_default(void); void futex_hash_free(struct mm_struct *mm); diff --git a/include/linux/sched.h b/include/linux/sched.h index 76cabfab5b73..de2f3cbe4953 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -1331,6 +1331,7 @@ struct task_struct { #endif #ifdef CONFIG_FUTEX struct robust_list_head __user *robust_list; + uintptr_t *futex_robust_lists; #ifdef CONFIG_COMPAT struct robust_list_head32 __user *robust_list32; #endif diff --git a/include/uapi/linux/futex.h b/include/uapi/linux/futex.h index 86efb089893d..2ba5c0c3bb59 100644 --- a/include/uapi/linux/futex.h +++ b/include/uapi/linux/futex.h @@ -163,6 +163,22 @@ struct robust_list_head32 { __u32 list_op_pending; }; =20 +/* + * Commands for set_robust_list2 syscall + */ +enum robust_list2_cmd { + FUTEX_ROBUST_LIST_CMD_SET_64, + FUTEX_ROBUST_LIST_CMD_SET_32, + FUTEX_ROBUST_LIST_CMD_LIST_LIMIT, + FUTEX_ROBUST_LIST_CMD_USER_MAX, + + /* + * Kernel internal, rejected for user space + */ + FUTEX_ROBUST_LIST_SET_NATIVE =3D 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 136639897ff9..14d8a7176367 100644 --- a/kernel/futex/core.c +++ b/kernel/futex/core.c @@ -71,6 +71,57 @@ struct futex_private_hash { struct futex_hash_bucket queues[]; }; =20 +int futex_robust_list_set(uintptr_t head, enum robust_list2_cmd cmd, + unsigned int index) +{ + uintptr_t entry =3D FUTEX_ROBUST_LIST_ENTRY_INUSE; + uintptr_t *rl =3D current->futex_robust_lists; + + if (!rl) { + rl =3D kcalloc(FUTEX_ROBUST_LIST2_MAX_IDX, sizeof(*rl), GFP_KERNEL); + if (!rl) + return -ENOMEM; + + scoped_guard(mutex, ¤t->futex_exit_mutex) { + /* check if another thread set the list before us */ + if (current->futex_robust_lists) { + kfree(rl); + rl =3D current->futex_robust_lists; + } else { + current->futex_robust_lists =3D rl; + } + } + + } + + switch (cmd) { + case FUTEX_ROBUST_LIST_CMD_SET_64: + if (futex_in_32bit_syscall()) + return -EINVAL; + break; + case FUTEX_ROBUST_LIST_CMD_SET_32: + entry |=3D FUTEX_ROBUST_LIST_ENTRY_32BIT; + break; + case FUTEX_ROBUST_LIST_SET_NATIVE: + index =3D FUTEX_ROBUST_LIST_NATIVE_IDX; + break; + case FUTEX_ROBUST_LIST_SET_COMPAT: + if (!IS_ENABLED(CONFIG_64BIT)) + return -EINVAL; + index =3D FUTEX_ROBUST_LIST_COMPAT_IDX; + entry |=3D FUTEX_ROBUST_LIST_ENTRY_32BIT; + break; + default: + return -EINVAL; + } + + entry |=3D head; + scoped_guard(mutex, ¤t->futex_exit_mutex) + rl[index] =3D entry; + + return 0; +} + /* * Fault injections for futexes. */ @@ -1150,9 +1201,8 @@ static inline int fetch_robust_entry(struct robust_li= st __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 =3D curr->robust_list; struct robust_list __user *entry, *next_entry, *pending; unsigned int limit =3D ROBUST_LIST_LIMIT, pi, pip; unsigned int next_pi; @@ -1244,9 +1294,8 @@ fetch_robust_entry32(u32 *uentry, struct robust_list = __user **entry, * * 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_lis= t_head32 __user *head) { - struct robust_list_head32 __user *head =3D curr->robust_list32; struct robust_list __user *entry, *next_entry, *pending; unsigned int limit =3D ROBUST_LIST_LIMIT, pi, pip; unsigned int next_pi; @@ -1311,7 +1360,15 @@ static void exit_robust_list32(struct task_struct *c= urr) handle_futex_death(uaddr, curr, pip, HANDLE_DEATH_PENDING); } } -#endif + +#else + +static void exit_robust_list32(struct task_struct *curr, struct robust_lis= t_head32 __user *head) +{ + pr_crit("32-bit kernel should never call %s", __func__); +} + +#endif /* CONFIG_64BIT */ =20 #ifdef CONFIG_FUTEX_PI =20 @@ -1404,20 +1461,60 @@ static void exit_pi_state_list(struct task_struct *= curr) static inline void exit_pi_state_list(struct task_struct *curr) { } #endif =20 +static void exit_robust_lists(struct task_struct *tsk) +{ + uintptr_t *rl =3D tsk->futex_robust_lists; + + tsk->futex_robust_lists =3D NULL; + + for (unsigned int idx =3D 0; idx < FUTEX_ROBUST_LIST2_MAX_IDX; idx++) { + uintptr_t entry =3D 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 &=3D FUTEX_ROBUST_LIST_ENTRY_MASK; + + head =3D (__force struct robust_list_head32 __user *)entry; + exit_robust_list32(tsk, head); + } else { + struct robust_list_head __user *head; + + entry &=3D FUTEX_ROBUST_LIST_ENTRY_MASK; + + head =3D (__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->robust_list)) { - exit_robust_list(tsk); + exit_robust_list(tsk, tsk->robust_list); tsk->robust_list =3D NULL; } =20 #ifdef CONFIG_64BIT if (unlikely(tsk->robust_list32)) { - exit_robust_list32(tsk); + exit_robust_list32(tsk, tsk->robust_list32); tsk->robust_list32 =3D NULL; } #endif =20 + if (unlikely(tsk->futex_robust_lists)) + exit_robust_lists(tsk); + if (unlikely(!list_empty(&tsk->pi_state_list))) exit_pi_state_list(tsk); } diff --git a/kernel/futex/syscalls.c b/kernel/futex/syscalls.c index 1de8ff230d54..0b7fa88aa34c 100644 --- a/kernel/futex/syscalls.c +++ b/kernel/futex/syscalls.c @@ -109,6 +109,47 @@ SYSCALL_DEFINE3(get_robust_list, int, pid, return put_user(head, head_ptr); } =20 +SYSCALL_DEFINE4(set_robust_list2, struct robust_list_head *, head, unsigne= d int, + index, unsigned int, cmd, unsigned int, flags) +{ + uintptr_t entry =3D (__force uintptr_t)head; + size_t align =3D sizeof(u32); + + if (flags) + return -EINVAL; + + if (cmd >=3D FUTEX_ROBUST_LIST_CMD_USER_MAX) + return -EINVAL; + + if (index >=3D FUTEX_ROBUST_LISTS_PER_USER) + 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 +=3D FUTEX_ROBUST_LIST2_IDX; + + switch (cmd) { + case FUTEX_ROBUST_LIST_CMD_SET_64: + if (futex_in_32bit_syscall()) + return -EOPNOTSUPP; + align =3D sizeof(u64); + fallthrough; + case FUTEX_ROBUST_LIST_CMD_SET_32: + if (entry % align) + return -EINVAL; + return futex_robust_list_set(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) { --=20 2.52.0 From nobody Tue Dec 2 01:08:01 2025 Received: from fanzine2.igalia.com (fanzine2.igalia.com [213.97.179.56]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 507142C0F70; Sat, 22 Nov 2025 05:51:24 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=213.97.179.56 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763790686; cv=none; b=Rs2VB0MBgKJwZUfeR3yye4f7arD4wEonlcbqgWXTlheHMwS2nLcZuFj2P9kLbS3E4sLRAZHSqq6whVaWdDWw5gLjqN1IApFbXlAbiJ2Lxq/UGE/kZdJ/F9YJoPIIcUdkP/81LurgUZqsdUwFs0c39ivHx/17oT8ASY9fKNu+yKM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763790686; c=relaxed/simple; bh=nkYmmv40aQmszbGW+EkkDhVeSBD05ty26Ze+T0qLGD8=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=DhqT9T3XW+detiUcVVeImjqQX5bMzpgxUcMFDR5Djzvs3Gnyenfcx14lDuSxXpPUVAW12x5LTVQ7nBLOadBCzoG07wA3ZA2yzWJ3kH6VpnQXXOpHIuGAQjDY6krKvTs/x3E7R4DPcb8ZjZ86UCLsvkGEBlLIcuM0sThxwQJPReE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=igalia.com; spf=pass smtp.mailfrom=igalia.com; dkim=pass (2048-bit key) header.d=igalia.com header.i=@igalia.com header.b=Z23pwq8o; arc=none smtp.client-ip=213.97.179.56 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=igalia.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=igalia.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=igalia.com header.i=@igalia.com header.b="Z23pwq8o" DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=igalia.com; s=20170329; h=Cc:To:In-Reply-To:References:Message-Id: Content-Transfer-Encoding:Content-Type:MIME-Version:Subject:Date:From:Sender: Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender :Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=Fz2SZAzQPFBi1wyteXTSmIxEEVHmQhv7pKOpper8CGI=; b=Z23pwq8oj0Fwx/0spVYX8rpPbO mMjtRNFAtDmCbWzGUOOU6WTsATQgjoY4UT78065ugrfXQPYxsUq3LlA3W3/3IKCVpQ9S666+0UXf0 kZuRducn9ND0psBSIrXRiLIz2NDWS2NZ0YIBPr4jfUI8dM9q4rqSFC7D52MfynohJ12t/gLnobH1P +xUkBsU3fjwdoAeYrWQEfbTlq4X4SQJo+oegA8tY17jshYX1bvh2sOGqv6YuORfJ7DN9ZmTWA0VGQ V8u0hDeqzYwJzyg59tl4EOoAynykMBKwbiL5iGbNSaII/YagVAqi4AQX38YRt1w1lxWwG7nugC84M 2w5XcRYA==; Received: from [187.101.0.152] (helo=[192.168.15.100]) by fanzine2.igalia.com with esmtpsa (Cipher TLS1.3:ECDHE_X25519__RSA_PSS_RSAE_SHA256__AES_256_GCM:256) (Exim) id 1vMgWl-003xEt-Vb; Sat, 22 Nov 2025 06:51:19 +0100 From: =?utf-8?q?Andr=C3=A9_Almeida?= Date: Sat, 22 Nov 2025 02:50:46 -0300 Subject: [PATCH v6 4/9] futex: Create get_robust_list2() syscall Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251122-tonyk-robust_futex-v6-4-05fea005a0fd@igalia.com> References: <20251122-tonyk-robust_futex-v6-0-05fea005a0fd@igalia.com> In-Reply-To: <20251122-tonyk-robust_futex-v6-0-05fea005a0fd@igalia.com> To: Thomas Gleixner , Ingo Molnar , Peter Zijlstra , Darren Hart , Davidlohr Bueso , Arnd Bergmann , Sebastian Andrzej Siewior , Waiman Long , Ryan Houdek Cc: linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-api@vger.kernel.org, kernel-dev@igalia.com, =?utf-8?q?Andr=C3=A9_Almeida?= X-Mailer: b4 0.14.3 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=C3=A9 Almeida --- For some reason I wasn't able to use put_user() for 32-bit lists.. it kept corrupting the value due to wrong write size I believe. copy_to_user() worked fine nonetheless. --- kernel/futex/syscalls.c | 61 +++++++++++++++++++++++++++++++++++++++++++++= ---- 1 file changed, 57 insertions(+), 4 deletions(-) diff --git a/kernel/futex/syscalls.c b/kernel/futex/syscalls.c index 0b7fa88aa34c..f730d16632fc 100644 --- a/kernel/futex/syscalls.c +++ b/kernel/futex/syscalls.c @@ -48,7 +48,7 @@ static inline void __user *futex_task_robust_list(struct = task_struct *p, bool co return p->robust_list; } =20 -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 =3D current; void __user *head; @@ -75,7 +75,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; =20 - head =3D futex_task_robust_list(p, compat); + if (index >=3D 0) { + scoped_guard(mutex, &p->futex_exit_mutex) { + uintptr_t *rl =3D p->futex_robust_lists; + + head =3D rl ? (void __user *) rl[index] : NULL; + } + } else { + head =3D futex_task_robust_list(p, compat); + } =20 up_read(&p->signal->exec_update_lock); put_task_struct(p); @@ -99,7 +107,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 =3D futex_get_robust_list_common(pid= , false); + struct robust_list_head __user *head =3D futex_get_robust_list_common(pid= , false, -1); =20 if (IS_ERR(head)) return PTR_ERR(head); @@ -150,6 +158,51 @@ SYSCALL_DEFINE4(set_robust_list2, struct robust_list_h= ead *, head, unsigned int, return -EINVAL; } =20 +SYSCALL_DEFINE4(get_robust_list2, int, pid, + void __user * __user *, head_ptr, + unsigned int, index, unsigned int, flags) +{ + void __user *entry_ptr; + uintptr_t entry; + + if (index >=3D 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 +=3D FUTEX_ROBUST_LIST2_IDX; + + entry_ptr =3D futex_get_robust_list_common(pid, false, index); + if (IS_ERR(entry_ptr)) + return PTR_ERR(entry_ptr); + + entry =3D (uintptr_t) entry_ptr; + + if (entry & FUTEX_ROBUST_LIST_ENTRY_32BIT) { + entry &=3D FUTEX_ROBUST_LIST_ENTRY_MASK; + + if (copy_to_user(head_ptr, &entry, sizeof(u32))) + return -EFAULT; + + return 0; + } else { + struct robust_list_head *head; + + entry &=3D FUTEX_ROBUST_LIST_ENTRY_MASK; + head =3D (__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) { @@ -524,7 +577,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 =3D futex_get_robust_list_common(p= id, true); + struct robust_list_head32 __user *head =3D futex_get_robust_list_common(p= id, true, -1); =20 if (IS_ERR(head)) return PTR_ERR(head); --=20 2.52.0 From nobody Tue Dec 2 01:08:01 2025 Received: from fanzine2.igalia.com (fanzine2.igalia.com [213.97.179.56]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E17C42C0F84; Sat, 22 Nov 2025 05:51:25 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=213.97.179.56 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763790687; cv=none; b=lCnIjcOueIAxt1g+QAzecV8C6Rt+dG0QLdvxLo8WiXhh/DVcCaO/IZctBQ3kGE4n5z4gazbYBoN8t5H7+oimEVepvLFGctYtsinolCIQQH7twumpCHHbQQm9La7XGQJX5sOL2NrsnqOVgXcoUjYCagR39lC8Vp1aEP+3RhvOe70= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763790687; c=relaxed/simple; bh=fWZH+ZH9sPvul/cfP6mD+erj4KfRIqOD7PMjYsJKDUw=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=pHDdaZdhPtH79hVTdq/o+O2+dv29CUhQw46ML0OtsNiOpoiYuMJEHEVASHOxltAYqIsdzw5xmlRPwMf2vBzdmnQ6nntjrfKNMJe/4JPxHPzwO5+VbD86sq6+lPZgWslQf46D0gVJ2eYw5tpnd1pmjJP5pUBPflaQKQCdhrHuGIw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=igalia.com; spf=pass smtp.mailfrom=igalia.com; dkim=pass (2048-bit key) header.d=igalia.com header.i=@igalia.com header.b=VZsm4dJQ; arc=none smtp.client-ip=213.97.179.56 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=igalia.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=igalia.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=igalia.com header.i=@igalia.com header.b="VZsm4dJQ" DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=igalia.com; s=20170329; h=Cc:To:In-Reply-To:References:Message-Id: Content-Transfer-Encoding:Content-Type:MIME-Version:Subject:Date:From:Sender: Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender :Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=OD0jRZ+fXfSPscUraJUmOXDMEdIwvwVQwdCE0K2Bw0c=; b=VZsm4dJQKxCn8DfwBt+0qxXvC4 Nnd38kNtPKGwVk0WG885tsFwGLsnTze/Z8Cn3Sljtnq0gbkhW+WP0YP5VF3IrsH+0Vb0eJQ2NHgQI O38ZiDOr87yuTkuHsTFP0LyDhI0XtmCna1bc7kCdNov+vK5tuBdifOGRNgxE4/Arx9ELX40ClyMik gUzAFfQ9OKM9y8kG0iR673ObypSDSiI0EN1XNXXX46uOIcT5ae9cVn7u5JkNxzQ+yTCXQEtp1mofP LSEGVYjuqWn23/gAo610xaxUyHlCJisJYAS5km5QP1R5CxgKbwxauJyUReZQAHSUt/dHQrBmJW8Ic s98/u5tA==; Received: from [187.101.0.152] (helo=[192.168.15.100]) by fanzine2.igalia.com with esmtpsa (Cipher TLS1.3:ECDHE_X25519__RSA_PSS_RSAE_SHA256__AES_256_GCM:256) (Exim) id 1vMgWp-003xEt-5N; Sat, 22 Nov 2025 06:51:22 +0100 From: =?utf-8?q?Andr=C3=A9_Almeida?= Date: Sat, 22 Nov 2025 02:50:47 -0300 Subject: [PATCH v6 5/9] futex: Wire up set_robust_list2 syscall Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251122-tonyk-robust_futex-v6-5-05fea005a0fd@igalia.com> References: <20251122-tonyk-robust_futex-v6-0-05fea005a0fd@igalia.com> In-Reply-To: <20251122-tonyk-robust_futex-v6-0-05fea005a0fd@igalia.com> To: Thomas Gleixner , Ingo Molnar , Peter Zijlstra , Darren Hart , Davidlohr Bueso , Arnd Bergmann , Sebastian Andrzej Siewior , Waiman Long , Ryan Houdek Cc: linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-api@vger.kernel.org, kernel-dev@igalia.com, =?utf-8?q?Andr=C3=A9_Almeida?= X-Mailer: b4 0.14.3 Wire up the new set_robust_list2 syscall in all available architectures. Signed-off-by: Andr=C3=A9 Almeida --- 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 ++++- kernel/sys_ni.c | 1 + scripts/syscall.tbl | 1 + 18 files changed, 21 insertions(+), 1 deletion(-) diff --git a/arch/alpha/kernel/syscalls/syscall.tbl b/arch/alpha/kernel/sys= calls/syscall.tbl index 16dca28ebf17..d0cb7b902cc6 100644 --- a/arch/alpha/kernel/syscalls/syscall.tbl +++ b/arch/alpha/kernel/syscalls/syscall.tbl @@ -509,3 +509,4 @@ 577 common open_tree_attr sys_open_tree_attr 578 common file_getattr sys_file_getattr 579 common file_setattr sys_file_setattr +580 common set_robust_list2 sys_set_robust_list2 diff --git a/arch/arm/tools/syscall.tbl b/arch/arm/tools/syscall.tbl index b07e699aaa3c..910e6e14ccf0 100644 --- a/arch/arm/tools/syscall.tbl +++ b/arch/arm/tools/syscall.tbl @@ -484,3 +484,4 @@ 467 common open_tree_attr sys_open_tree_attr 468 common file_getattr sys_file_getattr 469 common file_setattr sys_file_setattr +470 common set_robust_list2 sys_set_robust_list2 diff --git a/arch/m68k/kernel/syscalls/syscall.tbl b/arch/m68k/kernel/sysca= lls/syscall.tbl index f41d38dfbf13..eee3f320483d 100644 --- a/arch/m68k/kernel/syscalls/syscall.tbl +++ b/arch/m68k/kernel/syscalls/syscall.tbl @@ -469,3 +469,4 @@ 467 common open_tree_attr sys_open_tree_attr 468 common file_getattr sys_file_getattr 469 common file_setattr sys_file_setattr +470 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 580af574fe73..6c69d8ebbc38 100644 --- a/arch/microblaze/kernel/syscalls/syscall.tbl +++ b/arch/microblaze/kernel/syscalls/syscall.tbl @@ -475,3 +475,4 @@ 467 common open_tree_attr sys_open_tree_attr 468 common file_getattr sys_file_getattr 469 common file_setattr sys_file_setattr +470 common set_robust_list2 sys_set_robust_list2 diff --git a/arch/mips/kernel/syscalls/syscall_n32.tbl b/arch/mips/kernel/s= yscalls/syscall_n32.tbl index d824ffe9a014..f70db3741b0e 100644 --- a/arch/mips/kernel/syscalls/syscall_n32.tbl +++ b/arch/mips/kernel/syscalls/syscall_n32.tbl @@ -408,3 +408,4 @@ 467 n32 open_tree_attr sys_open_tree_attr 468 n32 file_getattr sys_file_getattr 469 n32 file_setattr sys_file_setattr +470 n32 set_robust_list2 sys_set_robust_list2 diff --git a/arch/mips/kernel/syscalls/syscall_n64.tbl b/arch/mips/kernel/s= yscalls/syscall_n64.tbl index 7a7049c2c307..9480488f9495 100644 --- a/arch/mips/kernel/syscalls/syscall_n64.tbl +++ b/arch/mips/kernel/syscalls/syscall_n64.tbl @@ -384,3 +384,4 @@ 467 n64 open_tree_attr sys_open_tree_attr 468 n64 file_getattr sys_file_getattr 469 n64 file_setattr sys_file_setattr +470 n64 set_robust_list2 sys_set_robust_list2 diff --git a/arch/mips/kernel/syscalls/syscall_o32.tbl b/arch/mips/kernel/s= yscalls/syscall_o32.tbl index d330274f0601..2761c9cd8946 100644 --- a/arch/mips/kernel/syscalls/syscall_o32.tbl +++ b/arch/mips/kernel/syscalls/syscall_o32.tbl @@ -457,3 +457,4 @@ 467 o32 open_tree_attr sys_open_tree_attr 468 o32 file_getattr sys_file_getattr 469 o32 file_setattr sys_file_setattr +470 o32 set_robust_list2 sys_set_robust_list2 diff --git a/arch/parisc/kernel/syscalls/syscall.tbl b/arch/parisc/kernel/s= yscalls/syscall.tbl index 88a788a7b18d..eb37fda5c48f 100644 --- a/arch/parisc/kernel/syscalls/syscall.tbl +++ b/arch/parisc/kernel/syscalls/syscall.tbl @@ -468,3 +468,4 @@ 467 common open_tree_attr sys_open_tree_attr 468 common file_getattr sys_file_getattr 469 common file_setattr sys_file_setattr +470 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 b453e80dfc00..472bebec449d 100644 --- a/arch/powerpc/kernel/syscalls/syscall.tbl +++ b/arch/powerpc/kernel/syscalls/syscall.tbl @@ -560,3 +560,4 @@ 467 common open_tree_attr sys_open_tree_attr 468 common file_getattr sys_file_getattr 469 common file_setattr sys_file_setattr +470 common set_robust_list2 sys_set_robust_list2 diff --git a/arch/s390/kernel/syscalls/syscall.tbl b/arch/s390/kernel/sysca= lls/syscall.tbl index 8a6744d658db..ba7fac304941 100644 --- a/arch/s390/kernel/syscalls/syscall.tbl +++ b/arch/s390/kernel/syscalls/syscall.tbl @@ -472,3 +472,4 @@ 467 common open_tree_attr sys_open_tree_attr sys_open_tree_attr 468 common file_getattr sys_file_getattr sys_file_getattr 469 common file_setattr sys_file_setattr sys_file_setattr +470 common set_robust_list2 sys_set_robust_list2 sys_set_robust_list2 diff --git a/arch/sh/kernel/syscalls/syscall.tbl b/arch/sh/kernel/syscalls/= syscall.tbl index 5e9c9eff5539..c05c94a742be 100644 --- a/arch/sh/kernel/syscalls/syscall.tbl +++ b/arch/sh/kernel/syscalls/syscall.tbl @@ -473,3 +473,4 @@ 467 common open_tree_attr sys_open_tree_attr 468 common file_getattr sys_file_getattr 469 common file_setattr sys_file_setattr +470 common set_robust_list2 sys_set_robust_list2 diff --git a/arch/sparc/kernel/syscalls/syscall.tbl b/arch/sparc/kernel/sys= calls/syscall.tbl index ebb7d06d1044..3a59f3008325 100644 --- a/arch/sparc/kernel/syscalls/syscall.tbl +++ b/arch/sparc/kernel/syscalls/syscall.tbl @@ -515,3 +515,4 @@ 467 common open_tree_attr sys_open_tree_attr 468 common file_getattr sys_file_getattr 469 common file_setattr sys_file_setattr +470 common set_robust_list2 sys_set_robust_list2 diff --git a/arch/x86/entry/syscalls/syscall_32.tbl b/arch/x86/entry/syscal= ls/syscall_32.tbl index 4877e16da69a..e9d6e1a1d777 100644 --- a/arch/x86/entry/syscalls/syscall_32.tbl +++ b/arch/x86/entry/syscalls/syscall_32.tbl @@ -475,3 +475,4 @@ 467 i386 open_tree_attr sys_open_tree_attr 468 i386 file_getattr sys_file_getattr 469 i386 file_setattr sys_file_setattr +470 i386 set_robust_list2 sys_set_robust_list2 diff --git a/arch/x86/entry/syscalls/syscall_64.tbl b/arch/x86/entry/syscal= ls/syscall_64.tbl index ced2a1deecd7..8fdcf090300d 100644 --- a/arch/x86/entry/syscalls/syscall_64.tbl +++ b/arch/x86/entry/syscalls/syscall_64.tbl @@ -394,6 +394,7 @@ 467 common open_tree_attr sys_open_tree_attr 468 common file_getattr sys_file_getattr 469 common file_setattr sys_file_setattr +470 common set_robust_list2 sys_set_robust_list2 =20 # # Due to a historical design error, certain syscalls are numbered differen= tly diff --git a/arch/xtensa/kernel/syscalls/syscall.tbl b/arch/xtensa/kernel/s= yscalls/syscall.tbl index 374e4cb788d8..d7bb6b9104dd 100644 --- a/arch/xtensa/kernel/syscalls/syscall.tbl +++ b/arch/xtensa/kernel/syscalls/syscall.tbl @@ -440,3 +440,4 @@ 467 common open_tree_attr sys_open_tree_attr 468 common file_getattr sys_file_getattr 469 common file_setattr sys_file_setattr +470 common set_robust_list2 sys_set_robust_list2 diff --git a/include/uapi/asm-generic/unistd.h b/include/uapi/asm-generic/u= nistd.h index 04e0077fb4c9..44fc87287983 100644 --- a/include/uapi/asm-generic/unistd.h +++ b/include/uapi/asm-generic/unistd.h @@ -858,8 +858,11 @@ __SYSCALL(__NR_file_getattr, sys_file_getattr) #define __NR_file_setattr 469 __SYSCALL(__NR_file_setattr, sys_file_setattr) =20 +#define __NR_set_robust_list2 470 +__SYSCALL(__NR_set_robust_list2, sys_set_robust_list2) + #undef __NR_syscalls -#define __NR_syscalls 470 +#define __NR_syscalls 471 =20 /* * 32 bit systems traditionally used different diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c index bf5d05c635ff..0ca2cfe69b11 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); =20 /* CONFIG_MMU only */ COND_SYSCALL(swapon); diff --git a/scripts/syscall.tbl b/scripts/syscall.tbl index d1ae5e92c615..58c334aa8922 100644 --- a/scripts/syscall.tbl +++ b/scripts/syscall.tbl @@ -410,3 +410,4 @@ 467 common open_tree_attr sys_open_tree_attr 468 common file_getattr sys_file_getattr 469 common file_setattr sys_file_setattr +470 common set_robust_list2 sys_set_robust_list2 --=20 2.52.0 From nobody Tue Dec 2 01:08:01 2025 Received: from fanzine2.igalia.com (fanzine2.igalia.com [213.97.179.56]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 966F62BE03D; Sat, 22 Nov 2025 05:51:29 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=213.97.179.56 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763790691; cv=none; b=qD74TVHb6s4DA8dIEKgE4WAVUQFeJRevB5FBHWE83gRLlnMom3DiMc1TWt3XK1G9Kg0CQjLRCOY8SjEsKVPAotx3xfRpryIUgs/ObyOaGCiJjRENQyJYH8BkqIsqa8QpebSluM7LghJRXv1yX+Mnwe0MQLDKDTHWSugQbdyqi1Q= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763790691; c=relaxed/simple; bh=hbNXjpY847J9gIEo/zUHDT1s0Qd3MFk6DEAx759fcDQ=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=rF8ghrfMhSRB1MlnPPGRfJYKhDjyHgV84iJ8gIUg6QzuBZZNiSigxKr9n+FDNDOqo35ZcnPhvqp281eM6HxZ+D6DOgwYuPHYdngvD9Lwh6iajNvrP0/ijsiSARPDlBRueCkASgISiKZ6wVkXDp/DboE1QssY6sUg6ryeJTHhUCM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=igalia.com; spf=pass smtp.mailfrom=igalia.com; dkim=pass (2048-bit key) header.d=igalia.com header.i=@igalia.com header.b=Wn6QIkGZ; arc=none smtp.client-ip=213.97.179.56 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=igalia.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=igalia.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=igalia.com header.i=@igalia.com header.b="Wn6QIkGZ" DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=igalia.com; s=20170329; h=Cc:To:In-Reply-To:References:Message-Id: Content-Transfer-Encoding:Content-Type:MIME-Version:Subject:Date:From:Sender: Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender :Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=oMl8VKqo68dtKQI1fBQMiaA54tMMEUZSj8LxMeoI1/0=; b=Wn6QIkGZak159bCkfkYXOOAltI FgAT9KU1syCjCS7HeexwhS6IAagZhJMgGd811x0omMxGZawSlwqWWgc3xPkJRXOy2ACA7ez0pY7yc oLcQ1VRnf771PKnwa2KTUbGY3M8/KfbyKrTW6RG7SaeSWv/nTz3oDmMqbhRHoJOFo/w0HGx1mR2pn Uy2sXLspaZWi9WDHzgk5nWRw3GqICVG0xUg3YuUbKsfXwWDtcnL+f9H+WVnK3ArmmkfI6ajk7jaQC shiTGEy0Q0VDWMC3oSwYinmkSpEidZfum33az937jwCC6mp/7E9nU5GpEwnOTpjhHsrC/7eBkNeqN eyBJYXyw==; Received: from [187.101.0.152] (helo=[192.168.15.100]) by fanzine2.igalia.com with esmtpsa (Cipher TLS1.3:ECDHE_X25519__RSA_PSS_RSAE_SHA256__AES_256_GCM:256) (Exim) id 1vMgWs-003xEt-BA; Sat, 22 Nov 2025 06:51:26 +0100 From: =?utf-8?q?Andr=C3=A9_Almeida?= Date: Sat, 22 Nov 2025 02:50:48 -0300 Subject: [PATCH v6 6/9] futex: Wire up get_robust_list2 syscall Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251122-tonyk-robust_futex-v6-6-05fea005a0fd@igalia.com> References: <20251122-tonyk-robust_futex-v6-0-05fea005a0fd@igalia.com> In-Reply-To: <20251122-tonyk-robust_futex-v6-0-05fea005a0fd@igalia.com> To: Thomas Gleixner , Ingo Molnar , Peter Zijlstra , Darren Hart , Davidlohr Bueso , Arnd Bergmann , Sebastian Andrzej Siewior , Waiman Long , Ryan Houdek Cc: linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-api@vger.kernel.org, kernel-dev@igalia.com, =?utf-8?q?Andr=C3=A9_Almeida?= X-Mailer: b4 0.14.3 Wire up the new get_robust_list2 syscall in all available architectures. Signed-off-by: Andr=C3=A9 Almeida --- 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 +++- kernel/sys_ni.c | 1 + 17 files changed, 19 insertions(+), 1 deletion(-) diff --git a/arch/alpha/kernel/syscalls/syscall.tbl b/arch/alpha/kernel/sys= calls/syscall.tbl index d0cb7b902cc6..b4a42beda6db 100644 --- a/arch/alpha/kernel/syscalls/syscall.tbl +++ b/arch/alpha/kernel/syscalls/syscall.tbl @@ -510,3 +510,4 @@ 578 common file_getattr sys_file_getattr 579 common file_setattr sys_file_setattr 580 common set_robust_list2 sys_set_robust_list2 +581 common get_robust_list2 sys_get_robust_list2 diff --git a/arch/arm/tools/syscall.tbl b/arch/arm/tools/syscall.tbl index 910e6e14ccf0..d4a4d8446cb0 100644 --- a/arch/arm/tools/syscall.tbl +++ b/arch/arm/tools/syscall.tbl @@ -485,3 +485,4 @@ 468 common file_getattr sys_file_getattr 469 common file_setattr sys_file_setattr 470 common set_robust_list2 sys_set_robust_list2 +471 common get_robust_list2 sys_get_robust_list2 diff --git a/arch/m68k/kernel/syscalls/syscall.tbl b/arch/m68k/kernel/sysca= lls/syscall.tbl index eee3f320483d..c2f1c5a3313c 100644 --- a/arch/m68k/kernel/syscalls/syscall.tbl +++ b/arch/m68k/kernel/syscalls/syscall.tbl @@ -470,3 +470,4 @@ 468 common file_getattr sys_file_getattr 469 common file_setattr sys_file_setattr 470 common set_robust_list2 sys_set_robust_list2 +471 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 6c69d8ebbc38..1389dd194eec 100644 --- a/arch/microblaze/kernel/syscalls/syscall.tbl +++ b/arch/microblaze/kernel/syscalls/syscall.tbl @@ -476,3 +476,4 @@ 468 common file_getattr sys_file_getattr 469 common file_setattr sys_file_setattr 470 common set_robust_list2 sys_set_robust_list2 +471 common get_robust_list2 sys_get_robust_list2 diff --git a/arch/mips/kernel/syscalls/syscall_n32.tbl b/arch/mips/kernel/s= yscalls/syscall_n32.tbl index f70db3741b0e..e149d2ddbc2f 100644 --- a/arch/mips/kernel/syscalls/syscall_n32.tbl +++ b/arch/mips/kernel/syscalls/syscall_n32.tbl @@ -409,3 +409,4 @@ 468 n32 file_getattr sys_file_getattr 469 n32 file_setattr sys_file_setattr 470 n32 set_robust_list2 sys_set_robust_list2 +471 n32 get_robust_list2 sys_get_robust_list2 diff --git a/arch/mips/kernel/syscalls/syscall_n64.tbl b/arch/mips/kernel/s= yscalls/syscall_n64.tbl index 9480488f9495..7ddddc89a751 100644 --- a/arch/mips/kernel/syscalls/syscall_n64.tbl +++ b/arch/mips/kernel/syscalls/syscall_n64.tbl @@ -385,3 +385,4 @@ 468 n64 file_getattr sys_file_getattr 469 n64 file_setattr sys_file_setattr 470 n64 set_robust_list2 sys_set_robust_list2 +471 n64 get_robust_list2 sys_get_robust_list2 diff --git a/arch/mips/kernel/syscalls/syscall_o32.tbl b/arch/mips/kernel/s= yscalls/syscall_o32.tbl index 2761c9cd8946..c0a5ebafed1a 100644 --- a/arch/mips/kernel/syscalls/syscall_o32.tbl +++ b/arch/mips/kernel/syscalls/syscall_o32.tbl @@ -458,3 +458,4 @@ 468 o32 file_getattr sys_file_getattr 469 o32 file_setattr sys_file_setattr 470 o32 set_robust_list2 sys_set_robust_list2 +471 o32 get_robust_list2 sys_get_robust_list2 diff --git a/arch/parisc/kernel/syscalls/syscall.tbl b/arch/parisc/kernel/s= yscalls/syscall.tbl index eb37fda5c48f..4c6cb64ec113 100644 --- a/arch/parisc/kernel/syscalls/syscall.tbl +++ b/arch/parisc/kernel/syscalls/syscall.tbl @@ -469,3 +469,4 @@ 468 common file_getattr sys_file_getattr 469 common file_setattr sys_file_setattr 470 common set_robust_list2 sys_set_robust_list2 +471 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 472bebec449d..1475fa6b3ee3 100644 --- a/arch/powerpc/kernel/syscalls/syscall.tbl +++ b/arch/powerpc/kernel/syscalls/syscall.tbl @@ -561,3 +561,4 @@ 468 common file_getattr sys_file_getattr 469 common file_setattr sys_file_setattr 470 common set_robust_list2 sys_set_robust_list2 +470 common get_robust_list2 sys_get_robust_list2 diff --git a/arch/s390/kernel/syscalls/syscall.tbl b/arch/s390/kernel/sysca= lls/syscall.tbl index ba7fac304941..b8161ee922ef 100644 --- a/arch/s390/kernel/syscalls/syscall.tbl +++ b/arch/s390/kernel/syscalls/syscall.tbl @@ -473,3 +473,4 @@ 468 common file_getattr sys_file_getattr sys_file_getattr 469 common file_setattr sys_file_setattr sys_file_setattr 470 common set_robust_list2 sys_set_robust_list2 sys_set_robust_list2 +471 common get_robust_list2 sys_get_robust_list2 sys_get_robust_list2 diff --git a/arch/sh/kernel/syscalls/syscall.tbl b/arch/sh/kernel/syscalls/= syscall.tbl index c05c94a742be..566baa152634 100644 --- a/arch/sh/kernel/syscalls/syscall.tbl +++ b/arch/sh/kernel/syscalls/syscall.tbl @@ -474,3 +474,4 @@ 468 common file_getattr sys_file_getattr 469 common file_setattr sys_file_setattr 470 common set_robust_list2 sys_set_robust_list2 +471 common get_robust_list2 sys_get_robust_list2 diff --git a/arch/sparc/kernel/syscalls/syscall.tbl b/arch/sparc/kernel/sys= calls/syscall.tbl index 3a59f3008325..fb3844c17711 100644 --- a/arch/sparc/kernel/syscalls/syscall.tbl +++ b/arch/sparc/kernel/syscalls/syscall.tbl @@ -516,3 +516,4 @@ 468 common file_getattr sys_file_getattr 469 common file_setattr sys_file_setattr 470 common set_robust_list2 sys_set_robust_list2 +471 common get_robust_list2 sys_get_robust_list2 diff --git a/arch/x86/entry/syscalls/syscall_32.tbl b/arch/x86/entry/syscal= ls/syscall_32.tbl index e9d6e1a1d777..0df93458ef37 100644 --- a/arch/x86/entry/syscalls/syscall_32.tbl +++ b/arch/x86/entry/syscalls/syscall_32.tbl @@ -476,3 +476,4 @@ 468 i386 file_getattr sys_file_getattr 469 i386 file_setattr sys_file_setattr 470 i386 set_robust_list2 sys_set_robust_list2 +471 i386 get_robust_list2 sys_get_robust_list2 diff --git a/arch/x86/entry/syscalls/syscall_64.tbl b/arch/x86/entry/syscal= ls/syscall_64.tbl index 8fdcf090300d..e7fdcc3d6e52 100644 --- a/arch/x86/entry/syscalls/syscall_64.tbl +++ b/arch/x86/entry/syscalls/syscall_64.tbl @@ -395,6 +395,7 @@ 468 common file_getattr sys_file_getattr 469 common file_setattr sys_file_setattr 470 common set_robust_list2 sys_set_robust_list2 +471 common get_robust_list2 sys_get_robust_list2 =20 # # Due to a historical design error, certain syscalls are numbered differen= tly diff --git a/arch/xtensa/kernel/syscalls/syscall.tbl b/arch/xtensa/kernel/s= yscalls/syscall.tbl index d7bb6b9104dd..bd63dbc78c0e 100644 --- a/arch/xtensa/kernel/syscalls/syscall.tbl +++ b/arch/xtensa/kernel/syscalls/syscall.tbl @@ -441,3 +441,4 @@ 468 common file_getattr sys_file_getattr 469 common file_setattr sys_file_setattr 470 common set_robust_list2 sys_set_robust_list2 +471 common get_robust_list2 sys_get_robust_list2 diff --git a/include/uapi/asm-generic/unistd.h b/include/uapi/asm-generic/u= nistd.h index 44fc87287983..9539e893c9ac 100644 --- a/include/uapi/asm-generic/unistd.h +++ b/include/uapi/asm-generic/unistd.h @@ -860,9 +860,11 @@ __SYSCALL(__NR_file_setattr, sys_file_setattr) =20 #define __NR_set_robust_list2 470 __SYSCALL(__NR_set_robust_list2, sys_set_robust_list2) +#define __NR_get_robust_list2 471 +__SYSCALL(__NR_get_robust_list2, sys_get_robust_list2) =20 #undef __NR_syscalls -#define __NR_syscalls 471 +#define __NR_syscalls 472 =20 /* * 32 bit systems traditionally used different diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c index 0ca2cfe69b11..0a7f7634446c 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); =20 /* CONFIG_MMU only */ COND_SYSCALL(swapon); --=20 2.52.0 From nobody Tue Dec 2 01:08:01 2025 Received: from fanzine2.igalia.com (fanzine2.igalia.com [213.97.179.56]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 807862BEFE8; Sat, 22 Nov 2025 05:51:33 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=213.97.179.56 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763790697; cv=none; b=fKEGtA63ArXRyeXcYAf7d/cvDCn1Cg58tnMS+JF8lC11f3SulAtdEQQdtz3hq6JCFeslTce15m+HP6KpdymV1wXvzRNt1XLUps0qgiylhhEnmLlWweo9qnftQO7BWt3Pv2MSD2uQxKNDXllzUI5EKz+PT/aFak5LUUWuSH1rJO0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763790697; c=relaxed/simple; bh=nso+CpOJpPRJzd43Dl8ff2FCkPlbBHzXlwd/WnDkI78=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=b26gnVOJ0RQ+sUs9KEfcoJtf4Va0OLCJZNUcyyAj9II5qdY7gZN28xqb1LrnoU4WLg/5Cw4zl3BO9Ag0eLkssZAdckkEJ4qxC5HM3nA2qYOXy/oZSv7EtE55myihkvXQVpt0CEw0j3Cdo1yH/OzMLGDshs10bzJPXNn6SeBeMRQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=igalia.com; spf=pass smtp.mailfrom=igalia.com; dkim=pass (2048-bit key) header.d=igalia.com header.i=@igalia.com header.b=dVfge20E; arc=none smtp.client-ip=213.97.179.56 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=igalia.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=igalia.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=igalia.com header.i=@igalia.com header.b="dVfge20E" DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=igalia.com; s=20170329; h=Cc:To:In-Reply-To:References:Message-Id: Content-Transfer-Encoding:Content-Type:MIME-Version:Subject:Date:From:Sender: Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender :Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=+L/tOyy8M0DyWtdQicdo29LsLyCaZTO29YU1zlSFePI=; b=dVfge20E/ggOVpv5kMRv3uE5gE q9Q2RWKPO/DHN0u+1ptRIclNYiG4+f24klHjLQANR39drTY0FfsUJIk8VlFj2AKXksOpC7NkUzRg8 HjKW2g1tHYbjK7c/TEb6UCr+wq11+wG0XdkUVFFmNxABqF0HzJA3j6XGqJx/Ym7ls5aiqzlI5Lnx7 +IlKx/X6qNkwqX03wRqEBYrjTDxj1TggyjUO+AeEh75iD4hsnqLI86SwX8j4PXUGQdu2lNOLji8Sk v2no1CfBkZNkc1hBlPz3ze4ll5Uooj34pRfGDcepfbAsxaDjiBjOTV41LJ22yfGZx4DBk13cf8/ph SPloxU4Q==; Received: from [187.101.0.152] (helo=[192.168.15.100]) by fanzine2.igalia.com with esmtpsa (Cipher TLS1.3:ECDHE_X25519__RSA_PSS_RSAE_SHA256__AES_256_GCM:256) (Exim) id 1vMgWv-003xEt-Gs; Sat, 22 Nov 2025 06:51:29 +0100 From: =?utf-8?q?Andr=C3=A9_Almeida?= Date: Sat, 22 Nov 2025 02:50:49 -0300 Subject: [PATCH v6 7/9] selftests/futex: Expand for set_robust_list2() Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251122-tonyk-robust_futex-v6-7-05fea005a0fd@igalia.com> References: <20251122-tonyk-robust_futex-v6-0-05fea005a0fd@igalia.com> In-Reply-To: <20251122-tonyk-robust_futex-v6-0-05fea005a0fd@igalia.com> To: Thomas Gleixner , Ingo Molnar , Peter Zijlstra , Darren Hart , Davidlohr Bueso , Arnd Bergmann , Sebastian Andrzej Siewior , Waiman Long , Ryan Houdek Cc: linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-api@vger.kernel.org, kernel-dev@igalia.com, =?utf-8?q?Andr=C3=A9_Almeida?= X-Mailer: b4 0.14.3 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=C3=A9 Almeida --- .../selftests/futex/functional/robust_list.c | 409 +++++++++++++++++= ++-- 1 file changed, 387 insertions(+), 22 deletions(-) diff --git a/tools/testing/selftests/futex/functional/robust_list.c b/tools= /testing/selftests/futex/functional/robust_list.c index e7d1254e18ca..bf47e9ab2951 100644 --- a/tools/testing/selftests/futex/functional/robust_list.c +++ b/tools/testing/selftests/futex/functional/robust_list.c @@ -42,6 +42,27 @@ =20 #define SLEEP_US 100 =20 +#ifndef SYS_set_robust_list2 +# define SYS_set_robust_list2 470 + +enum robust_list_cmd { + FUTEX_ROBUST_LIST_CMD_SET_64, + FUTEX_ROBUST_LIST_CMD_SET_32, + FUTEX_ROBUST_LIST_CMD_LIST_LIMIT, + FUTEX_ROBUST_LIST_CMD_USER_MAX, +}; + +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; =20 static int set_robust_list(struct robust_list_head *head, size_t len) @@ -54,6 +75,58 @@ static int get_robust_list(int pid, struct robust_list_h= ead **head, size_t *len_ return syscall(SYS_get_robust_list, pid, head, len_ptr); } =20 +static int set_robust_list2(struct robust_list_head *head, int index, + enum robust_list_cmd cmd, unsigned int flags) +{ + return syscall(SYS_set_robust_list2, head, index, cmd, flags); +} + +static bool robust_list2_support(void) +{ + int ret =3D set_robust_list2(0, 0, FUTEX_ROBUST_LIST_CMD_LIST_LIMIT, 0); + + if (ret =3D=3D -1 && errno =3D=3D ENOSYS) + return false; + + return true; +} + +/* + * Return the set command according to the app bitness + */ +static int get_cmd_set(void) +{ + return sizeof(uintptr_t) =3D=3D 8 ? FUTEX_ROBUST_LIST_CMD_SET_64 : + FUTEX_ROBUST_LIST_CMD_SET_32; +} + +FIXTURE(robust_api) {}; + +FIXTURE_VARIANT(robust_api) +{ + bool robust2; +}; + +FIXTURE_SETUP(robust_api) +{ + if (!variant->robust2) + return; + + ASSERT_NE(robust_list2_support(), false); +} + +FIXTURE_TEARDOWN(robust_api) {} + +FIXTURE_VARIANT_ADD(robust_api, robust1) +{ + .robust2 =3D false, +}; + +FIXTURE_VARIANT_ADD(robust_api, robust2) +{ + .robust2 =3D true, +}; + /* * Basic lock struct, contains just the futex word and the robust list ele= ment * Real implementations have also a *prev to easily walk in the list @@ -61,6 +134,12 @@ static int get_robust_list(int pid, struct robust_list_= head **head, size_t *len_ struct lock_struct { _Atomic(unsigned int) futex; struct robust_list list; + bool robust2; +}; + +struct lock_struct32 { + _Atomic(uint32_t) futex; + struct robust_list32 list; }; =20 /* @@ -89,20 +168,17 @@ static int create_child(int (*fn)(void *arg), void *ar= g) /* * 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 =3D set_robust_list(head, sizeof(*head)); - if (ret) - return ret; - head->futex_offset =3D (size_t) offsetof(struct lock_struct, futex) - (size_t) offsetof(struct lock_struct, list); head->list.next =3D &head->list; head->list_op_pending =3D NULL; =20 - return 0; + if (!robust2) + return set_robust_list(head, sizeof(*head)); + + return set_robust_list2(head, index, get_cmd_set(), 0); } =20 /* @@ -174,7 +250,7 @@ static int child_fn_lock(void *arg) struct robust_list_head head; int ret; =20 - ret =3D set_list(&head); + ret =3D set_list(&head, lock->robust2, 0); if (ret) { ksft_test_result_fail("set_robust_list error\n"); return ret; @@ -204,14 +280,16 @@ 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 =3D { .futex =3D 0 }; _Atomic(unsigned int) *futex =3D &lock.futex; - struct robust_list_head head; int ret, pid, wstatus; + struct robust_list_head head; =20 - ret =3D set_list(&head); + lock.robust2 =3D variant->robust2; + + ret =3D set_list(&head, lock.robust2, 0); ASSERT_EQ(ret, 0); =20 /* @@ -270,6 +348,46 @@ TEST(test_set_robust_list_invalid_size) ksft_test_result_pass("%s\n", __func__); } =20 +/* + * Test invalid parameters + */ +TEST(test_set_robust_list2_inval) +{ + struct robust_list_head head; + int ret, list_limit; + + if (!robust_list2_support()) { + ksft_test_result_skip("robust_list2 not supported\n"); + return; + } + + /* Bad flag */ + ret =3D set_robust_list2(&head, 0, get_cmd_set(), 999); + ASSERT_EQ(ret, -1); + ASSERT_EQ(errno, EINVAL); + + /* Bad index */ + list_limit =3D set_robust_list2(NULL, 0, FUTEX_ROBUST_LIST_CMD_LIST_LIMIT= , 0); + ASSERT_GT(list_limit, 0); + + ret =3D set_robust_list2(&head, -1, get_cmd_set(), 0); + ASSERT_EQ(ret, -1); + ASSERT_EQ(errno, EINVAL); + + ret =3D set_robust_list2(&head, list_limit + 1, get_cmd_set(), 0); + ASSERT_EQ(ret, -1); + ASSERT_EQ(errno, EINVAL); + + /* Bad command */ + ret =3D set_robust_list2(&head, 0, FUTEX_ROBUST_LIST_CMD_USER_MAX, 0); + ASSERT_EQ(ret, -1); + ASSERT_EQ(errno, EINVAL); + + ret =3D set_robust_list2(&head, 0, -1, 0); + ASSERT_EQ(ret, -1); + ASSERT_EQ(errno, EINVAL); +} + /* * Test get_robust_list with pid =3D 0, getting the list of the running th= read */ @@ -363,7 +481,7 @@ static int child_fn_lock_with_error(void *arg) struct robust_list_head head; int ret; =20 - ret =3D set_list(&head); + ret =3D set_list(&head, false, 0); if (ret) { ksft_test_result_fail("set_robust_list error\n"); return -1; @@ -388,14 +506,16 @@ static int child_fn_lock_with_error(void *arg) * earlier, just after setting list_op_pending and taking the lock, to tes= t the * list_op_pending mechanism */ -TEST(test_set_list_op_pending) +TEST_F(robust_api, test_set_list_op_pending) { struct lock_struct lock =3D { .futex =3D 0 }; _Atomic(unsigned int) *futex =3D &lock.futex; - struct robust_list_head head; int ret, wstatus; + struct robust_list_head head; + + lock.robust2 =3D variant->robust2; =20 - ret =3D set_list(&head); + ret =3D set_list(&head, lock.robust2, 0); ASSERT_EQ(ret, 0); =20 ret =3D pthread_barrier_init(&barrier, NULL, 2); @@ -429,7 +549,7 @@ static int child_lock_holder(void *arg) struct robust_list_head head; int i; =20 - set_list(&head); + set_list(&head, locks[0].robust2, 0); =20 for (i =3D 0; i < CHILD_NR; i++) { locks[i].futex =3D 0; @@ -471,12 +591,19 @@ static int child_wait_lock(void *arg) * Test a robust list of more than one element. All the waiters should wak= e 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; =20 + if (!robust_list2_support()) { + ksft_test_result_skip("robust_list2 not supported\n"); + return; + } + + locks[0].robust2 =3D variant->robust2; + ret =3D pthread_barrier_init(&barrier, NULL, 2); ASSERT_EQ(ret, 0); ret =3D pthread_barrier_init(&barrier2, NULL, CHILD_NR + 1); @@ -507,13 +634,98 @@ TEST(test_robust_list_multiple_elements) ksft_test_result_pass("%s\n", __func__); } =20 +static int child_lock_holder_multiple_lists(void *arg) +{ + struct lock_struct *locks =3D arg; + struct robust_list_head *heads; + int i, list_limit; + + list_limit =3D set_robust_list2(NULL, 0, FUTEX_ROBUST_LIST_CMD_LIST_LIMIT= , 0); + + heads =3D malloc(list_limit * sizeof(*heads)); + if (!heads) + return -1; + + for (i =3D 0; i < list_limit; i++) { + set_list(&heads[i], true, i); + locks[i].futex =3D 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); + + 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()) { + ksft_test_result_skip("robust_list2 not supported\n"); + return; + } + + list_limit =3D set_robust_list2(NULL, 0, FUTEX_ROBUST_LIST_CMD_LIST_LIMIT= , 0); + ASSERT_GT(list_limit, 1); + + locks =3D malloc(list_limit * sizeof(*locks)); + ASSERT_NE(locks, NULL); + + pids =3D malloc(list_limit * sizeof(*pids)); + ASSERT_NE(pids, NULL); + + ret =3D pthread_barrier_init(&barrier, NULL, 2); + ASSERT_EQ(ret, 0); + ret =3D pthread_barrier_init(&barrier2, NULL, list_limit + 1); + ASSERT_EQ(ret, 0); + + pids[0] =3D create_child(&child_lock_holder_multiple_lists, locks); + + /* Wait until the locker thread takes the look */ + pthread_barrier_wait(&barrier); + + for (i =3D 0; i < list_limit; i++) + pids[i+1] =3D create_child(&child_wait_lock, &locks[i]); + + /* Wait for all children to return */ + ret =3D 0; + + for (i =3D 0; i < list_limit; i++) { + waitpid(pids[i], &wstatus, 0); + if (WEXITSTATUS(wstatus)) + ret =3D -1; + } + + pthread_barrier_destroy(&barrier); + pthread_barrier_destroy(&barrier2); + + /* Pass only if the child hasn't return error */ + if (!ret) + ksft_test_result_pass("%s\n", __func__); + + free(locks); + free(pids); +} + static int child_circular_list(void *arg) { - static struct robust_list_head head; + struct robust_list_head head; struct lock_struct a, b, c; + bool robust2 =3D *(bool *) arg; int ret; =20 - ret =3D set_list(&head); + ret =3D set_list(&head, robust2, 0); if (ret) { ksft_test_result_fail("set_list error\n"); return -1; @@ -536,11 +748,12 @@ static int child_circular_list(void *arg) * while processing it so it won't be trapped in an infinite loop while ha= ndling * a process exit */ -TEST(test_circular_list) +TEST_F(robust_api, test_circular_list) { int wstatus; + bool robust2 =3D variant->robust2; =20 - create_child(child_circular_list, NULL); + create_child(child_circular_list, &robust2); =20 wait(&wstatus); =20 @@ -549,4 +762,156 @@ TEST(test_circular_list) ksft_test_result_pass("%s\n", __func__); } =20 +/* + * 32-bit version of child_lock_holder.=20 + */ +static int child_lock_holder32(void *arg) +{ + struct lock_struct32 *locks =3D arg; + struct robust_list_head32 *head; + pid_t tid =3D gettid(); + int i, ret; + + head =3D mmap((void *)0x10000, sizeof(*head), PROT_READ | PROT_WRITE, + MAP_FIXED_NOREPLACE | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + + if (!head || ((uint32_t)(uintptr_t) head) > 0x7FFFFFFF) { + ksft_test_result_fail("child_lock_holder32 error\n"); + return -1; + } + + head->futex_offset =3D (uint32_t) ((size_t) offsetof(struct lock_struct32= , futex) - + (size_t) offsetof(struct lock_struct32, list)); + head->list.next =3D (uint32_t)(uintptr_t) &head->list; + head->list_op_pending =3D (uint32_t)(uintptr_t) NULL; + + ret =3D set_robust_list2((struct robust_list_head *) head, 0, + FUTEX_ROBUST_LIST_CMD_SET_32, 0); + if (ret) { + ksft_test_result_fail("set_robust_list2 error\n"); + return -1; + } + + /* + * Take all the locks and insert them in the list + */ + for (i =3D 0; i < CHILD_NR; i++) { + struct robust_list32 *list =3D &head->list; + + locks[i].futex =3D tid; + + while (list->next !=3D (uint32_t)(uintptr_t) &head->list) + list =3D (struct robust_list32 *)(uintptr_t) list->next; + + list->next =3D (uint32_t)(uintptr_t) &locks[i].list; + locks[i].list.next =3D (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 lock_struct32 *lock =3D arg; + _Atomic(unsigned int) *futex; + struct timespec to; + pid_t tid; + int ret; + + futex =3D &lock->futex; + + pthread_barrier_wait(&barrier2); + + to.tv_sec =3D FUTEX_TIMEOUT; + to.tv_nsec =3D 0; + + tid =3D atomic_load(futex); + + /* Kernel ignores futexes without the waiters flag */ + tid |=3D FUTEX_WAITERS; + atomic_store(futex, tid); + + ret =3D futex_wait((futex_t *) futex, tid, &to, 0); + + if (ret) { + ksft_test_result_fail("futex_wait error\n"); + return -1; + } + + if (!(lock->futex & FUTEX_OWNER_DIED)) { + ksft_test_result_fail("futex not marked with FUTEX_OWNER_DIED\n"); + return -1; + } + + 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 t= he + * mutex lock dance, just insert futexes in the list and check if the kern= el + * 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; + + if (sizeof(uintptr_t) !=3D 8) { + ksft_test_result_skip("Test only for 64-bit\n"); + return; + } + + if (!robust_list2_support()) { + ksft_test_result_skip("robust_list2 not supported\n"); + return; + } + + locks =3D mmap((void *)0x20000, sizeof(*locks) * CHILD_NR, + PROT_READ | PROT_WRITE, MAP_FIXED_NOREPLACE | MAP_PRIVATE | MAP_ANO= NYMOUS, + -1, 0); + + ASSERT_NE(locks, NULL); + ASSERT_LT((uintptr_t) locks, 0x7FFFFFFF); + + ret =3D pthread_barrier_init(&barrier, NULL, 2); + ASSERT_EQ(ret, 0); + ret =3D pthread_barrier_init(&barrier2, NULL, CHILD_NR + 1); + ASSERT_EQ(ret, 0); + + pids[0] =3D create_child(&child_lock_holder32, locks); + + /* Wait until the locker thread takes the look */ + pthread_barrier_wait(&barrier); + + for (i =3D 0; i < CHILD_NR; i++) + pids[i+1] =3D create_child(&child_wait_lock32, &locks[i]); + + /* Wait for all children to return */ + ret =3D 0; + + for (i =3D 0; i < CHILD_NR; i++) { + waitpid(pids[i], &wstatus, 0); + if (WEXITSTATUS(wstatus)) + ret =3D -1; + } + + pthread_barrier_destroy(&barrier); + pthread_barrier_destroy(&barrier2); + + /* Pass only if the child hasn't return error */ + if (!ret) + ksft_test_result_pass("%s\n", __func__); + + munmap(locks, sizeof(*locks) * CHILD_NR); +} + TEST_HARNESS_MAIN --=20 2.52.0 From nobody Tue Dec 2 01:08:01 2025 Received: from fanzine2.igalia.com (fanzine2.igalia.com [213.97.179.56]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id CEE212BF3CC; Sat, 22 Nov 2025 05:51:36 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=213.97.179.56 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763790698; cv=none; b=RI2swh1CAaeuRJzb2CHn03ldRgb6fblD/lz1Pg+k5Q+S60lXvAbM7Rc9trBrDr4IXVYHdwu/co1JYTlb8Ze77a/ypzkt7dkRaxcxGOgW40iO5HJK6oYBE3j56xDYjlJzZgr+zfDsnyO7KeQpa1lbPHhdcrArRP9gG3IWiiTQ63I= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763790698; c=relaxed/simple; bh=wuR9Um2tq6ZLxAMhCeO1aI1vzR2V/4QxRww9FgFxO+k=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Tz9bZeQtS5sAQ9y6TNPp90lIMHBJzONIBRTDVjmvAh1AAXnaLpRhSj+dAnMvN4n6uFPjfVccT6YXBglUGLncqnBlzr0W7Gn4FdjdqjyIXg3NF2cMUTrrmEbcXjFXS/JWfqoCejLpD8FXt98+mSGhINg4KkUzSb5lFIDzKZdIkKo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=igalia.com; spf=pass smtp.mailfrom=igalia.com; dkim=pass (2048-bit key) header.d=igalia.com header.i=@igalia.com header.b=iQsPBf/y; arc=none smtp.client-ip=213.97.179.56 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=igalia.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=igalia.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=igalia.com header.i=@igalia.com header.b="iQsPBf/y" DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=igalia.com; s=20170329; h=Cc:To:In-Reply-To:References:Message-Id: Content-Transfer-Encoding:Content-Type:MIME-Version:Subject:Date:From:Sender: Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender :Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=LKeIFtce+QsZcKJRLYOqSL7Yn9CvqGTf+rY/2k+4SUM=; b=iQsPBf/y1zugpmsmXvi3q3F7vS fuxgWKGLLEHjAl84au4opyj/rlgtjvqPFyv/a4De1lpEp1lB6jxPEuTui78cofYIgHBq5gPrjUNq7 B1Cr5xOA+vy9Z4ZBWKKR8/yA49ShiMYfsbsDsqNzfLIQ3qgtVRNX2aX2qOWXUB5CK/rHIV8dzOOrz x3jm4275/hL4Xlpbrz9AMRFUQTH1daXR5jlfs6OKCPImxn0azKI7VJmnpBvse5xsOhBsMpDfvAFOE dmobrJan9iSLCwk1yIAzcyVLK8qwyoHcfcllkRK8uTy64e/VIOydNwUIhFdjHsrp1E4b81JnifMpj Ooj0hBIQ==; Received: from [187.101.0.152] (helo=[192.168.15.100]) by fanzine2.igalia.com with esmtpsa (Cipher TLS1.3:ECDHE_X25519__RSA_PSS_RSAE_SHA256__AES_256_GCM:256) (Exim) id 1vMgWy-003xEt-Mh; Sat, 22 Nov 2025 06:51:32 +0100 From: =?utf-8?q?Andr=C3=A9_Almeida?= Date: Sat, 22 Nov 2025 02:50:50 -0300 Subject: [PATCH v6 8/9] selftests/futex: Expand for get_robust_list2() Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251122-tonyk-robust_futex-v6-8-05fea005a0fd@igalia.com> References: <20251122-tonyk-robust_futex-v6-0-05fea005a0fd@igalia.com> In-Reply-To: <20251122-tonyk-robust_futex-v6-0-05fea005a0fd@igalia.com> To: Thomas Gleixner , Ingo Molnar , Peter Zijlstra , Darren Hart , Davidlohr Bueso , Arnd Bergmann , Sebastian Andrzej Siewior , Waiman Long , Ryan Houdek Cc: linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-api@vger.kernel.org, kernel-dev@igalia.com, =?utf-8?q?Andr=C3=A9_Almeida?= X-Mailer: b4 0.14.3 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=C3=A9 Almeida --- .../selftests/futex/functional/robust_list.c | 95 ++++++++++++++++++= ---- 1 file changed, 81 insertions(+), 14 deletions(-) diff --git a/tools/testing/selftests/futex/functional/robust_list.c b/tools= /testing/selftests/futex/functional/robust_list.c index bf47e9ab2951..e6b26d7b9502 100644 --- a/tools/testing/selftests/futex/functional/robust_list.c +++ b/tools/testing/selftests/futex/functional/robust_list.c @@ -44,6 +44,7 @@ =20 #ifndef SYS_set_robust_list2 # define SYS_set_robust_list2 470 +# define SYS_get_robust_list2 471 =20 enum robust_list_cmd { FUTEX_ROBUST_LIST_CMD_SET_64, @@ -81,6 +82,12 @@ static int set_robust_list2(struct robust_list_head *hea= d, int index, return syscall(SYS_set_robust_list2, head, index, cmd, flags); } =20 +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 =3D set_robust_list2(0, 0, FUTEX_ROBUST_LIST_CMD_LIST_LIMIT, 0); @@ -181,6 +188,23 @@ static int set_list(struct robust_list_head *head, boo= l robust2, int index) return set_robust_list2(head, index, get_cmd_set(), 0); } =20 +static int get_list(pid_t pid, struct robust_list_head **head, bool robust= 2, int index) +{ + int ret; + + if (!robust2) { + size_t len_ptr; + + ret =3D get_robust_list(pid, head, &len_ptr); + if (sizeof(**head) !=3D len_ptr) + return -EINVAL; + + return ret; + } + + return get_robust_list2(pid, head, index, 0); +} + /* * A basic (and incomplete) mutex lock function with robustness */ @@ -391,37 +415,44 @@ TEST(test_set_robust_list2_inval) /* * Test get_robust_list with pid =3D 0, getting the list of the running th= read */ -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 =3D sizeof(head), len_ptr; + bool robust2 =3D variant->robust2; int ret; =20 - ret =3D set_robust_list(&head, head_size); + ret =3D set_list(&head, robust2, 0); ASSERT_EQ(ret, 0); =20 - ret =3D get_robust_list(0, &get_head, &len_ptr); + ret =3D get_list(0, &get_head, robust2, 0); ASSERT_EQ(ret, 0); ASSERT_EQ(get_head, &head); - ASSERT_EQ(head_size, len_ptr); =20 - ret =3D set_robust_list(&head2, head_size); + ret =3D set_list(&head2, robust2, 0); ASSERT_EQ(ret, 0); =20 - ret =3D get_robust_list(0, &get_head, &len_ptr); + ret =3D get_list(0, &get_head, robust2, 0); ASSERT_EQ(ret, 0); ASSERT_EQ(get_head, &head2); - ASSERT_EQ(head_size, len_ptr); =20 ksft_test_result_pass("%s\n", __func__); } =20 +struct child_arg_struct { + struct robust_list_head *head; + bool robust2; +}; + static int child_list(void *arg) { - struct robust_list_head *head =3D arg; + struct child_arg_struct *child =3D arg; + struct robust_list_head *head; + bool robust2 =3D child->robust2; int ret; =20 - ret =3D set_robust_list(head, sizeof(*head)); + head =3D child->head; + + ret =3D set_list(head, robust2, 0); if (ret) { ksft_test_result_fail("set_robust_list error\n"); return -1; @@ -444,23 +475,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 =3D variant->robust2; + struct child_arg_struct child =3D + {.robust2 =3D robust2, .head =3D &head}; int ret, wstatus; - size_t len_ptr; pid_t tid; =20 + ret =3D pthread_barrier_init(&barrier, NULL, 2); ret =3D pthread_barrier_init(&barrier2, NULL, 2); ASSERT_EQ(ret, 0); =20 - tid =3D create_child(&child_list, &head); + tid =3D create_child(&child_list, &child); ASSERT_NE(tid, -1); =20 pthread_barrier_wait(&barrier); =20 - ret =3D get_robust_list(tid, &get_head, &len_ptr); + ret =3D get_list(tid, &get_head, robust2, 0); ASSERT_EQ(ret, 0); ASSERT_EQ(&head, get_head); =20 @@ -914,4 +948,37 @@ TEST(test_32bit_lists) munmap(locks, sizeof(*locks) * CHILD_NR); } =20 +/* + * Test setting and getting mutiples head lists + */ +TEST(set_and_get_robust2) +{ + struct robust_list_head *head =3D NULL, *heads; + int i, list_limit, ret; + + if (!robust_list2_support()) { + ksft_test_result_skip("robust_list2 not supported\n"); + return; + } + + list_limit =3D set_robust_list2(NULL, 0, FUTEX_ROBUST_LIST_CMD_LIST_LIMIT= , 0); + + heads =3D malloc(list_limit * sizeof(*heads)); + ASSERT_NE(heads, NULL); + + for (i =3D 0; i < list_limit; i++) { + ret =3D set_list(&heads[i], true, i); + ASSERT_EQ(ret, 0); + } + + for (i =3D 0; i < list_limit; i++) { + ret =3D get_list(0, &head, true, i); + ASSERT_EQ(ret, 0); + ASSERT_EQ(head, &heads[i]); + } + + free(heads); + ksft_test_result_pass("%s\n", __func__); +} + TEST_HARNESS_MAIN --=20 2.52.0 From nobody Tue Dec 2 01:08:01 2025 Received: from fanzine2.igalia.com (fanzine2.igalia.com [213.97.179.56]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9390F2D3A70; Sat, 22 Nov 2025 05:51:39 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=213.97.179.56 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763790701; cv=none; b=rmEJvyH8nv+HGLKKydsoli8CvX01y9uxlGk8bOPVTeF0aNSWreyutKWOi29cF51WZhSaZLvjnwLpu4nQr/sAlAtH9lQD9FcJBZrLkWUg803aJoyNL8jSkgzPr57CdgMIugflYEpQIe6alrwd8ZHFLFaMg7GuAhy22Orj3uwjTtc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763790701; c=relaxed/simple; bh=LwIHhYXeFJeDdF1kDSEARDffQgz5dUmhKnAXQwo8Pn8=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=XjUFhwvHJkAdzFZJlDYGMIZwZtafAZBHWS3HSyezNwSDmFv/c/lbTV/RWwLWspJjYtPSgZdO52d9yNnHUrxvNnjTYMjGBecv84TuM1jU2p1xNm7OqRIO1UOkqzeOTTTIhAGy0yCf8DkjaIiNJwRpjzOidz1Hv5V4474qkRMpOt0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=igalia.com; spf=pass smtp.mailfrom=igalia.com; dkim=pass (2048-bit key) header.d=igalia.com header.i=@igalia.com header.b=W7D3ePx8; arc=none smtp.client-ip=213.97.179.56 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=igalia.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=igalia.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=igalia.com header.i=@igalia.com header.b="W7D3ePx8" DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=igalia.com; s=20170329; h=Cc:To:In-Reply-To:References:Message-Id: Content-Transfer-Encoding:Content-Type:MIME-Version:Subject:Date:From:Sender: Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender :Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=zOjPGE9lsonyPtm0p0zdTTkMf2zbS0u2zhJUFebOEG0=; b=W7D3ePx87PMqrJQuCOV3NeJPG3 kBh6S/y74nERtLvLkl3MoJZ2WWgWlKUQm6Mt1c061jzVhiCqLHmCE0mq9QtzPpK05VLiZGFYnVC12 CXdaXCgjPfVC+gMogBHGG5ip9vMRSqKreNNvORDYHFPzzPsQIJIY5JMqNY4G7ucre7wWwN4P1m/VL EdtH+V2/goa9iM6Z38OZLJpTJKlEA1toqO5RVP/iMXCzKir8JE/zRcEtDlALO0h4ts+NdPkHw8TKw XzR3S7un+kAnASjAhmFQTc8hb8aCNviGuvDP0WmvuScNNzyH5SXAa8YsrInJsYGW8KlohoX5ALpKI vzkQX3gg==; Received: from [187.101.0.152] (helo=[192.168.15.100]) by fanzine2.igalia.com with esmtpsa (Cipher TLS1.3:ECDHE_X25519__RSA_PSS_RSAE_SHA256__AES_256_GCM:256) (Exim) id 1vMgX1-003xEt-SV; Sat, 22 Nov 2025 06:51:35 +0100 From: =?utf-8?q?Andr=C3=A9_Almeida?= Date: Sat, 22 Nov 2025 02:50:51 -0300 Subject: [PATCH v6 9/9] futex: Use new robust list API internally Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251122-tonyk-robust_futex-v6-9-05fea005a0fd@igalia.com> References: <20251122-tonyk-robust_futex-v6-0-05fea005a0fd@igalia.com> In-Reply-To: <20251122-tonyk-robust_futex-v6-0-05fea005a0fd@igalia.com> To: Thomas Gleixner , Ingo Molnar , Peter Zijlstra , Darren Hart , Davidlohr Bueso , Arnd Bergmann , Sebastian Andrzej Siewior , Waiman Long , Ryan Houdek Cc: linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-api@vger.kernel.org, kernel-dev@igalia.com, =?utf-8?q?Andr=C3=A9_Almeida?= X-Mailer: b4 0.14.3 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=C3=A9 Almeida --- include/linux/futex.h | 4 ---- include/linux/sched.h | 5 ----- kernel/futex/core.c | 12 ------------ kernel/futex/syscalls.c | 52 ++++++++++++++++++++++++---------------------= ---- 4 files changed, 25 insertions(+), 48 deletions(-) diff --git a/include/linux/futex.h b/include/linux/futex.h index 3dba249bcd32..ce27f6307c60 100644 --- a/include/linux/futex.h +++ b/include/linux/futex.h @@ -87,10 +87,6 @@ static inline bool futex_in_32bit_syscall(void) =20 static inline void futex_init_task(struct task_struct *tsk) { - tsk->robust_list =3D NULL; -#ifdef CONFIG_COMPAT - tsk->robust_list32 =3D NULL; -#endif tsk->futex_robust_lists =3D NULL; INIT_LIST_HEAD(&tsk->pi_state_list); tsk->pi_state_cache =3D NULL; diff --git a/include/linux/sched.h b/include/linux/sched.h index de2f3cbe4953..e0f28e7f0a2d 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -75,7 +75,6 @@ struct pid_namespace; struct pipe_inode_info; struct rcu_node; struct reclaim_state; -struct robust_list_head; struct root_domain; struct rq; struct sched_attr; @@ -1330,11 +1329,7 @@ struct task_struct { u32 rmid; #endif #ifdef CONFIG_FUTEX - struct robust_list_head __user *robust_list; uintptr_t *futex_robust_lists; -#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 futex_exit_mutex; diff --git a/kernel/futex/core.c b/kernel/futex/core.c index 14d8a7176367..f91df175033d 100644 --- a/kernel/futex/core.c +++ b/kernel/futex/core.c @@ -1500,18 +1500,6 @@ static void exit_robust_lists(struct task_struct *ts= k) =20 static void futex_cleanup(struct task_struct *tsk) { - if (unlikely(tsk->robust_list)) { - exit_robust_list(tsk, tsk->robust_list); - tsk->robust_list =3D NULL; - } - -#ifdef CONFIG_64BIT - if (unlikely(tsk->robust_list32)) { - exit_robust_list32(tsk, tsk->robust_list32); - tsk->robust_list32 =3D NULL; - } -#endif - if (unlikely(tsk->futex_robust_lists)) exit_robust_lists(tsk); =20 diff --git a/kernel/futex/syscalls.c b/kernel/futex/syscalls.c index f730d16632fc..2a44791db37a 100644 --- a/kernel/futex/syscalls.c +++ b/kernel/futex/syscalls.c @@ -28,32 +28,29 @@ SYSCALL_DEFINE2(set_robust_list, struct robust_list_head __user *, head, size_t, len) { + enum robust_list2_cmd cmd; /* * The kernel knows only one size for now: */ if (unlikely(len !=3D sizeof(*head))) return -EINVAL; =20 - current->robust_list =3D head; + cmd =3D IS_ENABLED(CONFIG_64BIT) ? FUTEX_ROBUST_LIST_CMD_SET_64 : + FUTEX_ROBUST_LIST_CMD_SET_32; =20 - return 0; + return futex_robust_list_set((uintptr_t) head, cmd, + FUTEX_ROBUST_LIST_NATIVE_IDX); } =20 -static inline void __user *futex_task_robust_list(struct task_struct *p, b= ool compat) -{ -#ifdef CONFIG_COMPAT - if (compat) - return p->robust_list32; -#endif - return p->robust_list; -} - -static void __user *futex_get_robust_list_common(int pid, bool compat, int= index) +static void __user *futex_get_robust_list_common(int pid, unsigned int ind= ex) { struct task_struct *p =3D current; void __user *head; int ret; =20 + if (index >=3D FUTEX_ROBUST_LIST2_MAX_IDX) + return (void __user *)ERR_PTR(-EINVAL); + scoped_guard(rcu) { if (pid) { p =3D find_task_by_vpid(pid); @@ -75,14 +72,10 @@ static void __user *futex_get_robust_list_common(int pi= d, bool compat, int index if (!ptrace_may_access(p, PTRACE_MODE_READ_REALCREDS)) goto err_unlock; =20 - if (index >=3D 0) { - scoped_guard(mutex, &p->futex_exit_mutex) { - uintptr_t *rl =3D p->futex_robust_lists; + scoped_guard(mutex, &p->futex_exit_mutex) { + uintptr_t *rl =3D p->futex_robust_lists; =20 - head =3D rl ? (void __user *) rl[index] : NULL; - } - } else { - head =3D futex_task_robust_list(p, compat); + head =3D rl ? (void __user *) rl[index] : NULL; } =20 up_read(&p->signal->exec_update_lock); @@ -107,7 +100,11 @@ 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 =3D futex_get_robust_list_common(pid= , false, -1); + struct robust_list_head __user *head =3D + futex_get_robust_list_common(pid, FUTEX_ROBUST_LIST_NATIVE_IDX); + + head =3D (struct robust_list_head __user *) + ((uintptr_t) head & FUTEX_ROBUST_LIST_ENTRY_MASK); =20 if (IS_ERR(head)) return PTR_ERR(head); @@ -180,7 +177,7 @@ SYSCALL_DEFINE4(get_robust_list2, int, pid, */ index +=3D FUTEX_ROBUST_LIST2_IDX; =20 - entry_ptr =3D futex_get_robust_list_common(pid, false, index); + entry_ptr =3D futex_get_robust_list_common(pid, index); if (IS_ERR(entry_ptr)) return PTR_ERR(entry_ptr); =20 @@ -568,22 +565,23 @@ COMPAT_SYSCALL_DEFINE2(set_robust_list, if (unlikely(len !=3D sizeof(*head))) return -EINVAL; =20 - current->robust_list32 =3D head; - - return 0; + return futex_robust_list_set((uintptr_t) head, FUTEX_ROBUST_LIST_CMD_SET_= 32, + FUTEX_ROBUST_LIST_COMPAT_IDX); } =20 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 =3D futex_get_robust_list_common(p= id, true, -1); + struct robust_list_head32 __user *head =3D + futex_get_robust_list_common(pid, FUTEX_ROBUST_LIST_COMPAT_IDX); =20 - if (IS_ERR(head)) - return PTR_ERR(head); + head =3D (struct robust_list_head32 __user *) + ((uintptr_t) head & FUTEX_ROBUST_LIST_ENTRY_MASK); =20 if (put_user(sizeof(*head), len_ptr)) return -EFAULT; + return put_user(ptr_to_compat(head), head_ptr); } #endif /* CONFIG_COMPAT */ --=20 2.52.0