From: Jann Horn <jannh@google.com>
To: "Miguel Ojeda" <ojeda@kernel.org>,
"Boqun Feng" <boqun@kernel.org>, "Gary Guo" <gary@garyguo.net>,
"Björn Roy Baron" <bjorn3_gh@protonmail.com>,
"Benno Lossin" <lossin@kernel.org>,
"Andreas Hindborg" <a.hindborg@kernel.org>,
"Alice Ryhl" <aliceryhl@google.com>,
"Trevor Gross" <tmgross@umich.edu>,
"Danilo Krummrich" <dakr@kernel.org>
Cc: Wedson Almeida Filho <walmeida@microsoft.com>,
Martin Rodriguez Reboredo <yakoyoku@gmail.com>,
rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org,
Jann Horn <jannh@google.com>
Subject: [PATCH v2 1/2] rust: task: limit group_leader() to current
Date: Thu, 12 Feb 2026 23:12:06 +0100 [thread overview]
Message-ID: <20260212-rust-de_thread-v2-1-7d274c4fd02e@google.com> (raw)
In-Reply-To: <20260212-rust-de_thread-v2-0-7d274c4fd02e@google.com>
(Note: This is not a bugfix, it just cleans up an incorrect assumption.)
Task::group_leader() assumes that task::group_leader remains constant until
the task refcount drops to zero.
However, Linux has a special quirk where, when execve() is called by a
thread other than the thread group leader (the main thread), de_thread()
swaps the current thread's identity with the thread group leader's,
making the current thread the new thread group leader.
This means task::group_leader can't be assumed to be immutable for
non-current tasks.
For reference, you can see that accessing the ->group_leader of some random
task requires extra caution in the prlimit64() syscall, which grabs the
tasklist_lock and has a comment explaining that this is done to prevent
races with de_thread().
Signed-off-by: Jann Horn <jannh@google.com>
---
rust/kernel/task.rs | 26 +++++++++++++-------------
1 file changed, 13 insertions(+), 13 deletions(-)
diff --git a/rust/kernel/task.rs b/rust/kernel/task.rs
index 49fad6de0674..91ad88cdfd3b 100644
--- a/rust/kernel/task.rs
+++ b/rust/kernel/task.rs
@@ -103,7 +103,7 @@ macro_rules! current {
unsafe impl Send for Task {}
// SAFETY: It's OK to access `Task` through shared references from other threads because we're
-// either accessing properties that don't change (e.g., `pid`, `group_leader`) or that are properly
+// either accessing properties that don't change or that are properly
// synchronised by C code (e.g., `signal_pending`).
unsafe impl Sync for Task {}
@@ -204,18 +204,6 @@ pub fn as_ptr(&self) -> *mut bindings::task_struct {
self.0.get()
}
- /// Returns the group leader of the given task.
- pub fn group_leader(&self) -> &Task {
- // SAFETY: The group leader of a task never changes after initialization, so reading this
- // field is not a data race.
- let ptr = unsafe { *ptr::addr_of!((*self.as_ptr()).group_leader) };
-
- // SAFETY: The lifetime of the returned task reference is tied to the lifetime of `self`,
- // and given that a task has a reference to its group leader, we know it must be valid for
- // the lifetime of the returned task reference.
- unsafe { &*ptr.cast() }
- }
-
/// Returns the PID of the given task.
pub fn pid(&self) -> Pid {
// SAFETY: The pid of a task never changes after initialization, so reading this field is
@@ -345,6 +333,18 @@ pub fn active_pid_ns(&self) -> Option<&PidNamespace> {
// `release_task()` call.
Some(unsafe { PidNamespace::from_ptr(active_ns) })
}
+
+ /// Returns the group leader of the current task.
+ pub fn group_leader(&self) -> &Task {
+ // SAFETY: The group leader of the current task never changes in syscall
+ // context (except in the implementation of execve()).
+ let ptr = unsafe { *ptr::addr_of!((*self.as_ptr()).group_leader) };
+
+ // SAFETY: The lifetime of the returned task reference is tied to the lifetime of `self`,
+ // and given that a task has a reference to its group leader, we know it must be valid for
+ // the lifetime of the returned task reference.
+ unsafe { &*ptr.cast() }
+ }
}
// SAFETY: The type invariants guarantee that `Task` is always refcounted.
--
2.53.0.273.g2a3d683680-goog
next prev parent reply other threads:[~2026-02-12 22:12 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-02-12 22:12 [PATCH v2 0/2] rust: task: clean up safety issues wrt de_thread() Jann Horn
2026-02-12 22:12 ` Jann Horn [this message]
2026-02-13 7:52 ` [PATCH v2 1/2] rust: task: limit group_leader() to current Alice Ryhl
2026-02-13 13:37 ` Jann Horn
2026-02-13 13:42 ` Alice Ryhl
2026-02-12 22:12 ` [PATCH v2 2/2] rust: task: use atomic read for pid() Jann Horn
2026-02-13 16:20 ` Alice Ryhl
2026-02-13 16:49 ` Boqun Feng
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260212-rust-de_thread-v2-1-7d274c4fd02e@google.com \
--to=jannh@google.com \
--cc=a.hindborg@kernel.org \
--cc=aliceryhl@google.com \
--cc=bjorn3_gh@protonmail.com \
--cc=boqun@kernel.org \
--cc=dakr@kernel.org \
--cc=gary@garyguo.net \
--cc=linux-kernel@vger.kernel.org \
--cc=lossin@kernel.org \
--cc=ojeda@kernel.org \
--cc=rust-for-linux@vger.kernel.org \
--cc=tmgross@umich.edu \
--cc=walmeida@microsoft.com \
--cc=yakoyoku@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.