From: Boqun Feng <boqun.feng@gmail.com>
To: Alice Ryhl <aliceryhl@google.com>
Cc: "Miguel Ojeda" <ojeda@kernel.org>,
"Matthew Wilcox" <willy@infradead.org>,
"Al Viro" <viro@zeniv.linux.org.uk>,
"Andrew Morton" <akpm@linux-foundation.org>,
"Kees Cook" <keescook@chromium.org>,
"Alex Gaynor" <alex.gaynor@gmail.com>,
"Wedson Almeida Filho" <wedsonaf@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@samsung.com>,
"Greg Kroah-Hartman" <gregkh@linuxfoundation.org>,
"Arve Hjønnevåg" <arve@android.com>,
"Todd Kjos" <tkjos@android.com>,
"Martijn Coenen" <maco@android.com>,
"Joel Fernandes" <joel@joelfernandes.org>,
"Carlos Llamas" <cmllamas@google.com>,
"Suren Baghdasaryan" <surenb@google.com>,
"Arnd Bergmann" <arnd@arndb.de>,
linux-mm@kvack.org, linux-kernel@vger.kernel.org,
rust-for-linux@vger.kernel.org,
"Christian Brauner" <brauner@kernel.org>
Subject: Re: [PATCH v3 1/4] rust: uaccess: add userspace pointers
Date: Tue, 19 Mar 2024 19:27:38 -0700 [thread overview]
Message-ID: <ZfpJmmO2h4PxGshH@boqun-archlinux> (raw)
In-Reply-To: <20240311-alice-mm-v3-1-cdf7b3a2049c@google.com>
Hi Alice,
I was trying to work on a patch for UserSlice::read_slice(), and I found
a few place that may need some documentation improvements. Please see
below:
On Mon, Mar 11, 2024 at 10:47:13AM +0000, Alice Ryhl wrote:
[...]
> diff --git a/rust/kernel/uaccess.rs b/rust/kernel/uaccess.rs
> new file mode 100644
> index 000000000000..020f3847683f
> --- /dev/null
> +++ b/rust/kernel/uaccess.rs
> @@ -0,0 +1,315 @@
> +// SPDX-License-Identifier: GPL-2.0
> +
> +//! User pointers.
Since the type is renamed as UserSlice, maybe:
//! Slices to user space memory regions.
?
> +//!
> +//! C header: [`include/linux/uaccess.h`](srctree/include/linux/uaccess.h)
> +
> +use crate::{bindings, error::code::*, error::Result};
> +use alloc::vec::Vec;
> +use core::ffi::{c_ulong, c_void};
> +
> +/// A pointer to an area in userspace memory, which can be either read-only or
> +/// read-write.
> +///
> +/// All methods on this struct are safe: attempting to read or write invalid
> +/// pointers will return `EFAULT`. Concurrent access, *including data races
Probably reword this a little bit:
"All methods on this struct are safe: attempting to read or write on bad
addresses (either out of the bound of the slice or unmapped addresses)
will return `EFAULT`."
, please see below for the reason.
> +/// to/from userspace memory*, is permitted, because fundamentally another
> +/// userspace thread/process could always be modifying memory at the same time
> +/// (in the same way that userspace Rust's [`std::io`] permits data races with
> +/// the contents of files on disk). In the presence of a race, the exact byte
> +/// values read/written are unspecified but the operation is well-defined.
> +/// Kernelspace code should validate its copy of data after completing a read,
> +/// and not expect that multiple reads of the same address will return the same
> +/// value.
> +///
> +/// These APIs are designed to make it difficult to accidentally write TOCTOU
> +/// (time-of-check to time-of-use) bugs. Every time a memory location is read,
> +/// the reader's position is advanced by the read length and the next read will
> +/// start from there. This helps prevent accidentally reading the same location
> +/// twice and causing a TOCTOU bug.
> +///
> +/// Creating a [`UserSliceReader`] and/or [`UserSliceWriter`] consumes the
> +/// `UserSlice`, helping ensure that there aren't multiple readers or writers to
> +/// the same location.
> +///
> +/// If double-fetching a memory location is necessary for some reason, then that
> +/// is done by creating multiple readers to the same memory location, e.g. using
> +/// [`clone_reader`].
> +///
[...]
> + /// Reads raw data from the user slice into a raw kernel buffer.
> + ///
> + /// Fails with `EFAULT` if the read encounters a page fault.
Technically, this is not correct, since normal page faults can happen
during copy_from_user() (for example, userspace memory gets swapped). So
returning `EFAULT` really means the read happens on a bad address, which
also matches `EFAULT`'s definition:
EFAULT Bad address (POSIX.1-2001).
so maybe reword this and the similar ones below into something like:
/// Fails with `EFAULT` if the read happens on a bad address.
Otherwise, people may think that this function just abort whenever there
is a page fault. Thoughts?
Regards,
Boqun
> + ///
> + /// # Safety
> + ///
> + /// The `out` pointer must be valid for writing `len` bytes.
> + pub unsafe fn read_raw(&mut self, out: *mut u8, len: usize) -> Result {
> + if len > self.length {
> + return Err(EFAULT);
> + }
> + let Ok(len_ulong) = c_ulong::try_from(len) else {
> + return Err(EFAULT);
> + };
> + // SAFETY: The caller promises that `out` is valid for writing `len` bytes.
> + let res = unsafe { bindings::copy_from_user(out.cast::<c_void>(), self.ptr, len_ulong) };
> + if res != 0 {
> + return Err(EFAULT);
> + }
> + // Userspace pointers are not directly dereferencable by the kernel, so
> + // we cannot use `add`, which has C-style rules for defined behavior.
> + self.ptr = self.ptr.wrapping_byte_add(len);
> + self.length -= len;
> + Ok(())
> + }
> +
[...]
next prev parent reply other threads:[~2024-03-20 2:27 UTC|newest]
Thread overview: 29+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-03-11 10:47 [PATCH v3 0/4] Memory management patches needed by Rust Binder Alice Ryhl
2024-03-11 10:47 ` [PATCH v3 1/4] rust: uaccess: add userspace pointers Alice Ryhl
2024-03-16 14:16 ` Benno Lossin
2024-03-18 18:59 ` Boqun Feng
2024-03-18 19:12 ` Alice Ryhl
2024-03-18 19:33 ` Boqun Feng
2024-03-18 20:10 ` Alice Ryhl
2024-03-18 21:07 ` Boqun Feng
2024-03-20 2:27 ` Boqun Feng [this message]
2024-03-20 18:39 ` Boqun Feng
2024-03-11 10:47 ` [PATCH v3 2/4] uaccess: always export _copy_[from|to]_user with CONFIG_RUST Alice Ryhl
2024-03-18 21:16 ` Boqun Feng
2024-03-11 10:47 ` [PATCH v3 3/4] rust: uaccess: add typed accessors for userspace pointers Alice Ryhl
2024-03-16 14:56 ` Benno Lossin
2024-03-19 19:32 ` Boqun Feng
2024-03-11 10:47 ` [PATCH v3 4/4] rust: add abstraction for `struct page` Alice Ryhl
2024-03-11 10:50 ` Alice Ryhl
2024-03-15 8:16 ` Andreas Hindborg
2024-03-16 15:30 ` Matthew Wilcox
2024-03-16 20:39 ` Benno Lossin
2024-03-20 8:46 ` Alice Ryhl
2024-03-21 13:15 ` Benno Lossin
2024-03-21 13:42 ` Alice Ryhl
2024-03-21 13:56 ` Benno Lossin
2024-03-21 14:11 ` Alice Ryhl
2024-03-21 14:16 ` Alice Ryhl
2024-03-21 14:19 ` Benno Lossin
2024-03-19 22:16 ` Boqun Feng
2024-03-19 22:28 ` Benno Lossin
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=ZfpJmmO2h4PxGshH@boqun-archlinux \
--to=boqun.feng@gmail.com \
--cc=a.hindborg@samsung.com \
--cc=akpm@linux-foundation.org \
--cc=alex.gaynor@gmail.com \
--cc=aliceryhl@google.com \
--cc=arnd@arndb.de \
--cc=arve@android.com \
--cc=benno.lossin@proton.me \
--cc=bjorn3_gh@protonmail.com \
--cc=brauner@kernel.org \
--cc=cmllamas@google.com \
--cc=gary@garyguo.net \
--cc=gregkh@linuxfoundation.org \
--cc=joel@joelfernandes.org \
--cc=keescook@chromium.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=maco@android.com \
--cc=ojeda@kernel.org \
--cc=rust-for-linux@vger.kernel.org \
--cc=surenb@google.com \
--cc=tkjos@android.com \
--cc=viro@zeniv.linux.org.uk \
--cc=wedsonaf@gmail.com \
--cc=willy@infradead.org \
/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.