[PATCH 5/8] futex: take a lock-free exec_update_seq fast path in get_robust_list
From: Christian Brauner
Date: Mon May 25 2026 - 03:27:58 EST
Convert futex_get_robust_list_common() to
exec_update_read_begin_or_lock(): check ptrace_may_access() and read the
target's robust_list head lock-free, falling back to exec_update_lock on
a racing exec()/TSYNC. Nothing is referenced in the protected section, so
there is nothing to undo on retry. Read the head with READ_ONCE() since
the owner may update it concurrently.
Signed-off-by: Christian Brauner (Amutable) <brauner@xxxxxxxxxx>
---
kernel/futex/syscalls.c | 45 ++++++++++++++++++++---------------------
1 file changed, 22 insertions(+), 23 deletions(-)
diff --git a/kernel/futex/syscalls.c b/kernel/futex/syscalls.c
index 77ad9691f6a6..ec7a174f2682 100644
--- a/kernel/futex/syscalls.c
+++ b/kernel/futex/syscalls.c
@@ -43,16 +43,17 @@ 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 READ_ONCE(p->compat_robust_list);
#endif
- return p->robust_list;
+ return READ_ONCE(p->robust_list);
}
static void __user *futex_get_robust_list_common(int pid, bool compat)
{
struct task_struct *p = current;
void __user *head;
- int ret;
+ unsigned int seq = 0;
+ int err;
scoped_guard(rcu) {
if (pid) {
@@ -64,29 +65,27 @@ static void __user *futex_get_robust_list_common(int pid, bool compat)
}
/*
- * Hold exec_update_lock to serialize with concurrent exec()
- * so ptrace_may_access() is checked against stable credentials
+ * Serialize ptrace_may_access() against a concurrent exec() credential
+ * change; lock-free fast path with an exec_update_lock fallback.
*/
- ret = down_read_killable(&p->signal->exec_update_lock);
- if (ret)
- goto err_put;
-
- ret = -EPERM;
- if (!ptrace_may_access(p, PTRACE_MODE_READ_REALCREDS))
- goto err_unlock;
-
- head = futex_task_robust_list(p, compat);
-
- up_read(&p->signal->exec_update_lock);
+retry:
+ err = exec_update_read_begin_or_killable(p->signal, &seq);
+ if (err) {
+ head = (void __user *)ERR_PTR(err);
+ goto out;
+ }
+ if (ptrace_may_access(p, PTRACE_MODE_READ_REALCREDS))
+ head = futex_task_robust_list(p, compat);
+ else
+ head = (void __user *)ERR_PTR(-EPERM);
+ if (exec_update_read_needs_retry(p->signal, seq)) {
+ seq = 1;
+ goto retry;
+ }
+ exec_update_read_done(p->signal, seq);
+out:
put_task_struct(p);
-
return head;
-
-err_unlock:
- up_read(&p->signal->exec_update_lock);
-err_put:
- put_task_struct(p);
- return (void __user *)ERR_PTR(ret);
}
/**
--
2.47.3
--j3ezp33mpunnwnqz
Content-Type: text/x-diff; charset=utf-8
Content-Disposition: attachment;
filename="0006-kcmp-take-a-lock-free-exec_update_seq-fast-path.patch"