FROMGIT: rust: uaccess: add strncpy_from_user
This patch adds a direct wrapper around the C function of the same name. It's not really intended for direct use by Rust code since strncpy_from_user has a somewhat unfortunate API where it only nul-terminates the buffer if there's space for the nul-terminator. This means that a direct Rust wrapper around it could not return a &CStr since the buffer may not be a cstring. However, we still add the method to build more convenient APIs on top of it, which will happen in subsequent patches. Reviewed-by: Danilo Krummrich <dakr@kernel.org> Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Reviewed-by: Boqun Feng <boqun.feng@gmail.com> Reviewed-by: Benno Lossin <lossin@kernel.org> Signed-off-by: Alice Ryhl <aliceryhl@google.com> Link: https://lore.kernel.org/r/20250616-strncpy-from-user-v5-1-2d3fb0e1f5af@google.com [ Reworded title. - Miguel ] Signed-off-by: Miguel Ojeda <ojeda@kernel.org> Bug: 414339114 (cherry picked from commit 8da881d39c1b7fd4a211587ba40f1c936909a11a https://github.com/Rust-for-Linux/linux.git rust-next) Change-Id: I1455d14afbec4a4af1386618985f01a21b6dcf97 Signed-off-by: Alice Ryhl <aliceryhl@google.com>
This commit is contained in:
committed by
Isaac Manjarres
parent
bd6df18cfd
commit
0cb01a7d86
+35
-1
@@ -8,7 +8,7 @@ use crate::{
|
||||
alloc::{Allocator, Flags},
|
||||
bindings,
|
||||
error::Result,
|
||||
ffi::c_void,
|
||||
ffi::{c_char, c_void},
|
||||
prelude::*,
|
||||
types::{AsBytes, FromBytes},
|
||||
};
|
||||
@@ -370,3 +370,37 @@ impl UserSliceWriter {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Reads a nul-terminated string into `dst` and returns the length.
|
||||
///
|
||||
/// This reads from userspace until a NUL byte is encountered, or until `dst.len()` bytes have been
|
||||
/// read. Fails with [`EFAULT`] if a read happens on a bad address (some data may have been
|
||||
/// copied). When the end of the buffer is encountered, no NUL byte is added, so the string is
|
||||
/// *not* guaranteed to be NUL-terminated when `Ok(dst.len())` is returned.
|
||||
///
|
||||
/// # Guarantees
|
||||
///
|
||||
/// When this function returns `Ok(len)`, it is guaranteed that the first `len` bytes of `dst` are
|
||||
/// initialized and non-zero. Furthermore, if `len < dst.len()`, then `dst[len]` is a NUL byte.
|
||||
#[inline]
|
||||
#[expect(dead_code)]
|
||||
fn raw_strncpy_from_user(dst: &mut [MaybeUninit<u8>], src: UserPtr) -> Result<usize> {
|
||||
// CAST: Slice lengths are guaranteed to be `<= isize::MAX`.
|
||||
let len = dst.len() as isize;
|
||||
|
||||
// SAFETY: `dst` is valid for writing `dst.len()` bytes.
|
||||
let res = unsafe {
|
||||
bindings::strncpy_from_user(dst.as_mut_ptr().cast::<c_char>(), src as *const c_char, len)
|
||||
};
|
||||
|
||||
if res < 0 {
|
||||
return Err(Error::from_errno(res as i32));
|
||||
}
|
||||
|
||||
#[cfg(CONFIG_RUST_OVERFLOW_CHECKS)]
|
||||
assert!(res <= len);
|
||||
|
||||
// GUARANTEES: `strncpy_from_user` was successful, so `dst` has contents in accordance with the
|
||||
// guarantees of this function.
|
||||
Ok(res as usize)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user