All of lore.kernel.org
 help / color / mirror / Atom feed
From: Boqun Feng <boqun.feng@gmail.com>
To: Alice Ryhl <aliceryhl@google.com>
Cc: "Miguel Ojeda" <ojeda@kernel.org>,
	"Andrew Morton" <akpm@linux-foundation.org>,
	"Alexander Viro" <viro@zeniv.linux.org.uk>,
	"Greg Kroah-Hartman" <gregkh@linuxfoundation.org>,
	"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>,
	"Danilo Krummrich" <dakr@kernel.org>,
	rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH v2 2/2] uaccess: rust: add UserSliceReader::strcpy_into_buf
Date: Tue, 29 Apr 2025 11:02:07 -0700	[thread overview]
Message-ID: <68111422.050a0220.e6713.25af@mx.google.com> (raw)
In-Reply-To: <20250429-strncpy-from-user-v2-2-7e6facac0bf0@google.com>

On Tue, Apr 29, 2025 at 09:02:23AM +0000, Alice Ryhl wrote:
> This patch adds a more convenient method for reading C strings from
> userspace. Logic is added to NUL-terminate the buffer when necessary so
> that a &CStr can be returned.
> 
> Note that we treat attempts to read past `self.length` as a fault, so
> this returns EFAULT if that limit is exceeded before `buf.len()` is
> reached.
> 
> Signed-off-by: Alice Ryhl <aliceryhl@google.com>
> ---
>  rust/kernel/uaccess.rs | 35 +++++++++++++++++++++++++++++++++++
>  1 file changed, 35 insertions(+)
> 
> diff --git a/rust/kernel/uaccess.rs b/rust/kernel/uaccess.rs
> index acb703f074a30e60d42a222dd26aed80d8bdb76a..7cec1b62bd8b816f523c8be12cb29905740789fc 100644
> --- a/rust/kernel/uaccess.rs
> +++ b/rust/kernel/uaccess.rs
> @@ -293,6 +293,41 @@ pub fn read_all<A: Allocator>(mut self, buf: &mut Vec<u8, A>, flags: Flags) -> R
>          unsafe { buf.set_len(buf.len() + len) };
>          Ok(())
>      }
> +
> +    /// Read a NUL-terminated string from userspace and append it to `dst`.

s/`dst`/`buf`

?

> +    ///
> +    /// Fails with [`EFAULT`] if the read happens on a bad address.
> +    pub fn strcpy_into_buf<'buf>(&mut self, buf: &'buf mut [u8]) -> Result<&'buf CStr> {
> +        if buf.is_empty() {
> +            return Err(EINVAL);
> +        }
> +
> +        // SAFETY: The types are compatible and `strncpy_from_user` doesn't write uninitialized
> +        // bytes to `buf`.
> +        let mut dst = unsafe { &mut *(buf as *mut [u8] as *mut [MaybeUninit<u8>]) };

maybe:

	let mut dst = unsafe { &mut *(ptr::from_mut(buf).cast() };

? To align with:

	https://lore.kernel.org/rust-for-linux/20250418-ptr-as-ptr-v10-0-3d63d27907aa@gmail.com/	

> +
> +        // We never read more than `self.length` bytes.
> +        if dst.len() > self.length {
> +            dst = &mut dst[..self.length];
> +        }
> +
> +        let mut len = raw_strncpy_from_user(self.ptr, dst)?;
> +        if len < dst.len() {
> +            // Add one to include the NUL-terminator.
> +            len += 1;
> +        } else if len < buf.len() {
> +            // We hit the `self.length` limit before `buf.len()`.
> +            return Err(EFAULT);
> +        } else {
> +            // SAFETY: Due to the check at the beginning, the buffer is not empty.
> +            unsafe { *buf.last_mut().unwrap_unchecked() = 0 };
> +        }
> +        self.skip(len)?;
> +

So if the UserSlice content is "abcdefg" (not tailing NUL), and the buf
size is 4, after a strcpy_into_buf(), the return would be a CStr "abc"
(with a tailing NUL), and the UserSlice would move 4 bytes and become
"edg" (not tailing NUL), is this a desired behavior?

Alternatively, we can make `dst` always 1 byte less then `buf`, so that
in the above case, UserSlice will only move 3 bytes and become "defg",
and the return CStr is still "abc" (with a tailing NUL).

The current behavior makes me feel like we can lose some information,
for example, if the user-kernel protocol is that "a userslice that
contains 4 64-byte strings which don't have a tailing NUL", we cannot do
4 strcpy_into_buf() to get them, right? But of course, the scenario is
completely made up, just food for thoughts.

Regards,
Boqun

> +        // SAFETY: `raw_strncpy_from_user` guarantees that this range of bytes represents a
> +        // NUL-terminated string with the only NUL byte being at the end.
> +        Ok(unsafe { CStr::from_bytes_with_nul_unchecked(&buf[..len]) })
> +    }
>  }
>  
>  /// A writer for [`UserSlice`].
> 
> -- 
> 2.49.0.901.g37484f566f-goog
> 

  parent reply	other threads:[~2025-04-29 18:02 UTC|newest]

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-04-29  9:02 [PATCH v2 0/2] strncpy_from_user for Rust Alice Ryhl
2025-04-29  9:02 ` [PATCH v2 1/2] uaccess: rust: add strncpy_from_user Alice Ryhl
2025-04-29 10:11   ` Danilo Krummrich
2025-04-29 10:30     ` Alice Ryhl
2025-04-29 11:04   ` Greg Kroah-Hartman
2025-04-29 15:09     ` Alice Ryhl
2025-04-29 17:30   ` Boqun Feng
2025-04-29 20:28     ` John Hubbard
2025-04-29 20:31       ` Boqun Feng
2025-04-29  9:02 ` [PATCH v2 2/2] uaccess: rust: add UserSliceReader::strcpy_into_buf Alice Ryhl
2025-04-29 10:36   ` Danilo Krummrich
2025-04-29 11:09   ` Greg Kroah-Hartman
2025-04-29 11:38     ` Danilo Krummrich
2025-04-29 11:48       ` Greg Kroah-Hartman
2025-04-29 15:15         ` Alice Ryhl
2025-04-29 15:50           ` Greg Kroah-Hartman
2025-04-30 10:58     ` Alice Ryhl
2025-04-30 11:04       ` Greg Kroah-Hartman
2025-04-29 18:02   ` Boqun Feng [this message]
2025-04-29 18:26     ` Boqun Feng
2025-04-29 19:29     ` Alice Ryhl
2025-04-29 19:47       ` 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=68111422.050a0220.e6713.25af@mx.google.com \
    --to=boqun.feng@gmail.com \
    --cc=a.hindborg@kernel.org \
    --cc=akpm@linux-foundation.org \
    --cc=aliceryhl@google.com \
    --cc=benno.lossin@proton.me \
    --cc=bjorn3_gh@protonmail.com \
    --cc=dakr@kernel.org \
    --cc=gary@garyguo.net \
    --cc=gregkh@linuxfoundation.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.