From: Boqun Feng <boqun.feng@gmail.com>
To: Alice Ryhl <aliceryhl@google.com>
Cc: "Christian Brauner" <brauner@kernel.org>,
"Miguel Ojeda" <ojeda@kernel.org>,
"Alexander Viro" <viro@zeniv.linux.org.uk>,
"Jan Kara" <jack@suse.cz>, "Alex Gaynor" <alex.gaynor@gmail.com>,
"Gary Guo" <gary@garyguo.net>,
"Björn Roy Baron" <bjorn3_gh@protonmail.com>,
"Benno Lossin" <benno.lossin@proton.me>,
"Andreas Hindborg" <a.hindborg@kernel.org>,
"Trevor Gross" <tmgross@umich.edu>,
linux-fsdevel@vger.kernel.org, rust-for-linux@vger.kernel.org,
linux-kernel@vger.kernel.org
Subject: Re: [PATCH] rust: task: adjust safety comments in Task methods
Date: Tue, 15 Oct 2024 11:24:39 -0700 [thread overview]
Message-ID: <Zw6zZ00LOa1fkTTF@boqun-archlinux> (raw)
In-Reply-To: <20241015-task-safety-cmnts-v1-1-46ee92c82768@google.com>
On Tue, Oct 15, 2024 at 02:02:12PM +0000, Alice Ryhl wrote:
> The `Task` struct has several safety comments that aren't so great. For
> example, the reason that it's okay to read the `pid` is that the field
> is immutable, so there is no data race, which is not what the safety
> comment says.
>
> Thus, improve the safety comments. Also add an `as_ptr` helper. This
> makes it easier to read the various accessors on Task, as `self.0` may
> be confusing syntax for new Rust users.
>
> Signed-off-by: Alice Ryhl <aliceryhl@google.com>
> ---
> This is based on top of vfs.rust.file as the file series adds some new
> task methods. Christian, can you take this through that tree?
> ---
> rust/kernel/task.rs | 43 ++++++++++++++++++++++++-------------------
> 1 file changed, 24 insertions(+), 19 deletions(-)
>
> diff --git a/rust/kernel/task.rs b/rust/kernel/task.rs
> index 1a36a9f19368..080599075875 100644
> --- a/rust/kernel/task.rs
> +++ b/rust/kernel/task.rs
> @@ -145,11 +145,17 @@ fn deref(&self) -> &Self::Target {
> }
> }
>
> + /// Returns a raw pointer to the task.
> + #[inline]
> + pub fn as_ptr(&self) -> *mut bindings::task_struct {
FWIW, I think the name convention is `as_raw()` for a wrapper type of
`Opaque<T>` to return `*mut T`, e.g. `kernel::device::Device`.
Otherwise this looks good to me.
Regards,
Boqun
> + self.0.get()
> + }
> +
> /// Returns the group leader of the given task.
> pub fn group_leader(&self) -> &Task {
> - // SAFETY: By the type invariant, we know that `self.0` is a valid task. Valid tasks always
> - // have a valid `group_leader`.
> - let ptr = unsafe { *ptr::addr_of!((*self.0.get()).group_leader) };
> + // 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
> @@ -159,42 +165,41 @@ pub fn group_leader(&self) -> &Task {
>
> /// Returns the PID of the given task.
> pub fn pid(&self) -> Pid {
> - // SAFETY: By the type invariant, we know that `self.0` is a valid task. Valid tasks always
> - // have a valid pid.
> - unsafe { *ptr::addr_of!((*self.0.get()).pid) }
> + // SAFETY: The pid of a task never changes after initialization, so reading this field is
> + // not a data race.
> + unsafe { *ptr::addr_of!((*self.as_ptr()).pid) }
> }
>
> /// Returns the UID of the given task.
> pub fn uid(&self) -> Kuid {
> - // SAFETY: By the type invariant, we know that `self.0` is valid.
> - Kuid::from_raw(unsafe { bindings::task_uid(self.0.get()) })
> + // SAFETY: It's always safe to call `task_uid` on a valid task.
> + Kuid::from_raw(unsafe { bindings::task_uid(self.as_ptr()) })
> }
>
> /// Returns the effective UID of the given task.
> pub fn euid(&self) -> Kuid {
> - // SAFETY: By the type invariant, we know that `self.0` is valid.
> - Kuid::from_raw(unsafe { bindings::task_euid(self.0.get()) })
> + // SAFETY: It's always safe to call `task_euid` on a valid task.
> + Kuid::from_raw(unsafe { bindings::task_euid(self.as_ptr()) })
> }
>
> /// Determines whether the given task has pending signals.
> pub fn signal_pending(&self) -> bool {
> - // SAFETY: By the type invariant, we know that `self.0` is valid.
> - unsafe { bindings::signal_pending(self.0.get()) != 0 }
> + // SAFETY: It's always safe to call `signal_pending` on a valid task.
> + unsafe { bindings::signal_pending(self.as_ptr()) != 0 }
> }
>
> /// Returns the given task's pid in the current pid namespace.
> pub fn pid_in_current_ns(&self) -> Pid {
> - // SAFETY: We know that `self.0.get()` is valid by the type invariant, and passing a null
> - // pointer as the namespace is correct for using the current namespace.
> - unsafe { bindings::task_tgid_nr_ns(self.0.get(), ptr::null_mut()) }
> + // SAFETY: It's valid to pass a null pointer as the namespace (defaults to current
> + // namespace). The task pointer is also valid.
> + unsafe { bindings::task_tgid_nr_ns(self.as_ptr(), ptr::null_mut()) }
> }
>
> /// Wakes up the task.
> pub fn wake_up(&self) {
> - // SAFETY: By the type invariant, we know that `self.0.get()` is non-null and valid.
> - // And `wake_up_process` is safe to be called for any valid task, even if the task is
> + // SAFETY: It's always safe to call `signal_pending` on a valid task, even if the task
> // running.
> - unsafe { bindings::wake_up_process(self.0.get()) };
> + unsafe { bindings::wake_up_process(self.as_ptr()) };
> }
> }
>
> @@ -202,7 +207,7 @@ pub fn wake_up(&self) {
> unsafe impl crate::types::AlwaysRefCounted for Task {
> fn inc_ref(&self) {
> // SAFETY: The existence of a shared reference means that the refcount is nonzero.
> - unsafe { bindings::get_task_struct(self.0.get()) };
> + unsafe { bindings::get_task_struct(self.as_ptr()) };
> }
>
> unsafe fn dec_ref(obj: ptr::NonNull<Self>) {
>
> ---
> base-commit: 22018a5a54a3d353bf0fee7364b2b8018ed4c5a6
> change-id: 20241015-task-safety-cmnts-a7cfe4b2c470
>
> Best regards,
> --
> Alice Ryhl <aliceryhl@google.com>
>
next prev parent reply other threads:[~2024-10-15 18:25 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-10-15 14:02 [PATCH] rust: task: adjust safety comments in Task methods Alice Ryhl
2024-10-15 14:06 ` Christian Brauner
2024-10-15 17:19 ` Alice Ryhl
2024-10-15 14:07 ` Christian Brauner
2024-10-15 18:24 ` Boqun Feng [this message]
2024-10-15 18:37 ` Alice Ryhl
2024-10-15 18:45 ` Boqun Feng
2024-10-15 18:53 ` Alice Ryhl
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=Zw6zZ00LOa1fkTTF@boqun-archlinux \
--to=boqun.feng@gmail.com \
--cc=a.hindborg@kernel.org \
--cc=alex.gaynor@gmail.com \
--cc=aliceryhl@google.com \
--cc=benno.lossin@proton.me \
--cc=bjorn3_gh@protonmail.com \
--cc=brauner@kernel.org \
--cc=gary@garyguo.net \
--cc=jack@suse.cz \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=ojeda@kernel.org \
--cc=rust-for-linux@vger.kernel.org \
--cc=tmgross@umich.edu \
--cc=viro@zeniv.linux.org.uk \
/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.