From: Danilo Krummrich <dakr@xxxxxxxxxx> commit 58eff8e872bd04ccb3adcf99aec7334ffad06cfd upstream. Now that we got the kernel `Vec` in place, convert all existing `Vec` users to make use of it. Reviewed-by: Alice Ryhl <aliceryhl@xxxxxxxxxx> Reviewed-by: Benno Lossin <benno.lossin@xxxxxxxxx> Reviewed-by: Gary Guo <gary@xxxxxxxxxxx> Signed-off-by: Danilo Krummrich <dakr@xxxxxxxxxx> Link: https://lore.kernel.org/r/20241004154149.93856-20-dakr@xxxxxxxxxx [ Converted `kasan_test_rust.rs` too, as discussed. - Miguel ] Signed-off-by: Miguel Ojeda <ojeda@xxxxxxxxxx> Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx> --- mm/kasan/kasan_test_rust.rs | 2 +- rust/kernel/str.rs | 12 +++++------- rust/kernel/sync/locked_by.rs | 2 +- rust/kernel/types.rs | 2 +- rust/kernel/uaccess.rs | 17 +++++++---------- rust/macros/lib.rs | 6 +++--- samples/rust/rust_minimal.rs | 4 ++-- 7 files changed, 20 insertions(+), 25 deletions(-) --- a/mm/kasan/kasan_test_rust.rs +++ b/mm/kasan/kasan_test_rust.rs @@ -11,7 +11,7 @@ use kernel::prelude::*; /// drop the vector, and touch it. #[no_mangle] pub extern "C" fn kasan_test_rust_uaf() -> u8 { - let mut v: Vec<u8> = Vec::new(); + let mut v: KVec<u8> = KVec::new(); for _ in 0..4096 { v.push(0x42, GFP_KERNEL).unwrap(); } --- a/rust/kernel/str.rs +++ b/rust/kernel/str.rs @@ -2,8 +2,7 @@ //! String representations. -use crate::alloc::{flags::*, vec_ext::VecExt, AllocError}; -use alloc::vec::Vec; +use crate::alloc::{flags::*, AllocError, KVec}; use core::fmt::{self, Write}; use core::ops::{self, Deref, DerefMut, Index}; @@ -791,7 +790,7 @@ impl fmt::Write for Formatter { /// assert_eq!(s.is_ok(), false); /// ``` pub struct CString { - buf: Vec<u8>, + buf: KVec<u8>, } impl CString { @@ -804,7 +803,7 @@ impl CString { let size = f.bytes_written(); // Allocate a vector with the required number of bytes, and write to it. - let mut buf = <Vec<_> as VecExt<_>>::with_capacity(size, GFP_KERNEL)?; + let mut buf = KVec::with_capacity(size, GFP_KERNEL)?; // SAFETY: The buffer stored in `buf` is at least of size `size` and is valid for writes. let mut f = unsafe { Formatter::from_buffer(buf.as_mut_ptr(), size) }; f.write_fmt(args)?; @@ -851,10 +850,9 @@ impl<'a> TryFrom<&'a CStr> for CString { type Error = AllocError; fn try_from(cstr: &'a CStr) -> Result<CString, AllocError> { - let mut buf = Vec::new(); + let mut buf = KVec::new(); - <Vec<_> as VecExt<_>>::extend_from_slice(&mut buf, cstr.as_bytes_with_nul(), GFP_KERNEL) - .map_err(|_| AllocError)?; + buf.extend_from_slice(cstr.as_bytes_with_nul(), GFP_KERNEL)?; // INVARIANT: The `CStr` and `CString` types have the same invariants for // the string data, and we copied it over without changes. --- a/rust/kernel/sync/locked_by.rs +++ b/rust/kernel/sync/locked_by.rs @@ -43,7 +43,7 @@ use core::{cell::UnsafeCell, mem::size_o /// struct InnerDirectory { /// /// The sum of the bytes used by all files. /// bytes_used: u64, -/// _files: Vec<File>, +/// _files: KVec<File>, /// } /// /// struct Directory { --- a/rust/kernel/types.rs +++ b/rust/kernel/types.rs @@ -135,7 +135,7 @@ impl ForeignOwnable for () { /// # use kernel::types::ScopeGuard; /// fn example3(arg: bool) -> Result { /// let mut vec = -/// ScopeGuard::new_with_data(Vec::new(), |v| pr_info!("vec had {} elements\n", v.len())); +/// ScopeGuard::new_with_data(KVec::new(), |v| pr_info!("vec had {} elements\n", v.len())); /// /// vec.push(10u8, GFP_KERNEL)?; /// if arg { --- a/rust/kernel/uaccess.rs +++ b/rust/kernel/uaccess.rs @@ -11,7 +11,6 @@ use crate::{ prelude::*, types::{AsBytes, FromBytes}, }; -use alloc::vec::Vec; use core::ffi::{c_ulong, c_void}; use core::mem::{size_of, MaybeUninit}; @@ -46,7 +45,6 @@ pub type UserPtr = usize; /// every byte in the region. /// /// ```no_run -/// use alloc::vec::Vec; /// use core::ffi::c_void; /// use kernel::error::Result; /// use kernel::uaccess::{UserPtr, UserSlice}; @@ -54,7 +52,7 @@ pub type UserPtr = usize; /// fn bytes_add_one(uptr: UserPtr, len: usize) -> Result<()> { /// let (read, mut write) = UserSlice::new(uptr, len).reader_writer(); /// -/// let mut buf = Vec::new(); +/// let mut buf = KVec::new(); /// read.read_all(&mut buf, GFP_KERNEL)?; /// /// for b in &mut buf { @@ -69,7 +67,6 @@ pub type UserPtr = usize; /// Example illustrating a TOCTOU (time-of-check to time-of-use) bug. /// /// ```no_run -/// use alloc::vec::Vec; /// use core::ffi::c_void; /// use kernel::error::{code::EINVAL, Result}; /// use kernel::uaccess::{UserPtr, UserSlice}; @@ -78,21 +75,21 @@ pub type UserPtr = usize; /// fn is_valid(uptr: UserPtr, len: usize) -> Result<bool> { /// let read = UserSlice::new(uptr, len).reader(); /// -/// let mut buf = Vec::new(); +/// let mut buf = KVec::new(); /// read.read_all(&mut buf, GFP_KERNEL)?; /// /// todo!() /// } /// /// /// Returns the bytes behind this user pointer if they are valid. -/// fn get_bytes_if_valid(uptr: UserPtr, len: usize) -> Result<Vec<u8>> { +/// fn get_bytes_if_valid(uptr: UserPtr, len: usize) -> Result<KVec<u8>> { /// if !is_valid(uptr, len)? { /// return Err(EINVAL); /// } /// /// let read = UserSlice::new(uptr, len).reader(); /// -/// let mut buf = Vec::new(); +/// let mut buf = KVec::new(); /// read.read_all(&mut buf, GFP_KERNEL)?; /// /// // THIS IS A BUG! The bytes could have changed since we checked them. @@ -130,7 +127,7 @@ impl UserSlice { /// Reads the entirety of the user slice, appending it to the end of the provided buffer. /// /// Fails with [`EFAULT`] if the read happens on a bad address. - pub fn read_all(self, buf: &mut Vec<u8>, flags: Flags) -> Result { + pub fn read_all(self, buf: &mut KVec<u8>, flags: Flags) -> Result { self.reader().read_all(buf, flags) } @@ -291,9 +288,9 @@ impl UserSliceReader { /// Reads the entirety of the user slice, appending it to the end of the provided buffer. /// /// Fails with [`EFAULT`] if the read happens on a bad address. - pub fn read_all(mut self, buf: &mut Vec<u8>, flags: Flags) -> Result { + pub fn read_all(mut self, buf: &mut KVec<u8>, flags: Flags) -> Result { let len = self.length; - VecExt::<u8>::reserve(buf, len, flags)?; + buf.reserve(len, flags)?; // The call to `try_reserve` was successful, so the spare capacity is at least `len` bytes // long. --- a/rust/macros/lib.rs +++ b/rust/macros/lib.rs @@ -242,7 +242,7 @@ pub fn concat_idents(ts: TokenStream) -> /// #[pin_data] /// struct DriverData { /// #[pin] -/// queue: Mutex<Vec<Command>>, +/// queue: Mutex<KVec<Command>>, /// buf: KBox<[u8; 1024 * 1024]>, /// } /// ``` @@ -251,7 +251,7 @@ pub fn concat_idents(ts: TokenStream) -> /// #[pin_data(PinnedDrop)] /// struct DriverData { /// #[pin] -/// queue: Mutex<Vec<Command>>, +/// queue: Mutex<KVec<Command>>, /// buf: KBox<[u8; 1024 * 1024]>, /// raw_info: *mut Info, /// } @@ -281,7 +281,7 @@ pub fn pin_data(inner: TokenStream, item /// #[pin_data(PinnedDrop)] /// struct DriverData { /// #[pin] -/// queue: Mutex<Vec<Command>>, +/// queue: Mutex<KVec<Command>>, /// buf: KBox<[u8; 1024 * 1024]>, /// raw_info: *mut Info, /// } --- a/samples/rust/rust_minimal.rs +++ b/samples/rust/rust_minimal.rs @@ -13,7 +13,7 @@ module! { } struct RustMinimal { - numbers: Vec<i32>, + numbers: KVec<i32>, } impl kernel::Module for RustMinimal { @@ -21,7 +21,7 @@ impl kernel::Module for RustMinimal { pr_info!("Rust minimal sample (init)\n"); pr_info!("Am I built-in? {}\n", !cfg!(MODULE)); - let mut numbers = Vec::new(); + let mut numbers = KVec::new(); numbers.push(72, GFP_KERNEL)?; numbers.push(108, GFP_KERNEL)?; numbers.push(200, GFP_KERNEL)?; Patches currently in stable-queue which might be from ojeda@xxxxxxxxxx are queue-6.12/drm-panic-avoid-reimplementing-iterator-find.patch queue-6.12/documentation-rust-add-coding-guidelines-on-lints.patch queue-6.12/rust-provide-proper-code-documentation-titles.patch queue-6.12/rust-alloc-make-allocator-module-public.patch queue-6.12/rust-alloc-remove-vecext-extension.patch queue-6.12/rust-alloc-implement-reallocfunc.patch queue-6.12/rust-alloc-separate-aligned_size-from-krealloc_aligned.patch queue-6.12/rust-enable-clippy-unnecessary_safety_comment-lint.patch queue-6.12/rust-alloc-update-module-comment-of-alloc.rs.patch queue-6.12/rust-kbuild-expand-rusttest-target-for-macros.patch queue-6.12/rust-error-use-core-alloc-layouterror.patch queue-6.12/rust-str-test-replace-alloc-format.patch queue-6.12/loongarch-use-asm_reachable.patch queue-6.12/rust-alloc-implement-allocator-for-kmalloc.patch queue-6.12/rust-alloc-implement-collect-for-intoiter.patch queue-6.12/rust-alloc-introduce-arraylayout.patch queue-6.12/rust-alloc-implement-vmalloc-allocator.patch queue-6.12/documentation-rust-discuss-in-the-guidelines.patch queue-6.12/rust-error-check-for-config-test-in-error-name.patch queue-6.12/rust-enable-clippy-ignored_unit_patterns-lint.patch queue-6.12/rust-enable-clippy-unnecessary_safety_doc-lint.patch queue-6.12/rust-alloc-add-box-to-prelude.patch queue-6.12/kbuild-rust-remove-the-alloc-crate-and-globalalloc.patch queue-6.12/rust-alloc-add-allocator-trait.patch queue-6.12/rust-treewide-switch-to-our-kernel-box-type.patch queue-6.12/rust-introduce-.clippy.toml.patch queue-6.12/rust-alloc-rename-kernelallocator-to-kmalloc.patch queue-6.12/rust-alloc-implement-cmalloc-in-module-allocator_test.patch queue-6.12/drm-panic-allow-verbose-version-check.patch queue-6.12/rust-map-__kernel_size_t-and-friends-also-to-usize-isize.patch queue-6.12/rust-alloc-add-module-allocator_test.patch queue-6.12/rust-replace-clippy-dbg_macro-with-disallowed_macros.patch queue-6.12/rust-alloc-add-__gfp_nowarn-to-flags.patch queue-6.12/rust-enable-clippy-s-check-private-items.patch queue-6.12/rust-error-make-conversion-functions-public.patch queue-6.12/rust-sort-global-rust-flags.patch queue-6.12/rust-alloc-implement-contains-for-flags.patch queue-6.12/rust-init-remove-unneeded.patch queue-6.12/rust-use-custom-ffi-integer-types.patch queue-6.12/rust-sync-remove-unneeded.patch queue-6.12/rust-treewide-switch-to-the-kernel-vec-type.patch queue-6.12/rust-alloc-implement-kvmalloc-allocator.patch queue-6.12/drm-panic-correctly-indent-continuation-of-line-in-list-item.patch queue-6.12/rust-alloc-implement-kernel-vec-type.patch queue-6.12/rust-workqueue-remove-unneeded.patch queue-6.12/rust-error-optimize-error-type-to-use-nonzero.patch queue-6.12/drm-panic-remove-unnecessary-borrow-in-alignment_pattern.patch queue-6.12/rust-alloc-remove-extension-of-std-s-box.patch queue-6.12/rust-block-fix-formatting-in-gendisk-doc.patch queue-6.12/rust-enable-rustdoc-unescaped_backticks-lint.patch queue-6.12/rust-fix-size_t-in-bindgen-prototypes-of-c-builtins.patch queue-6.12/rust-enable-clippy-undocumented_unsafe_blocks-lint.patch queue-6.12/rust-alloc-add-vec-to-prelude.patch queue-6.12/rust-alloc-implement-intoiterator-for-vec.patch queue-6.12/rust-alloc-implement-kernel-box.patch queue-6.12/drm-panic-remove-redundant-field-when-assigning-value.patch queue-6.12/rust-types-avoid-repetition-in-as-from-bytes-impls.patch queue-6.12/rust-start-using-the-attribute.patch queue-6.12/drm-panic-allow-verbose-boolean-for-clarity.patch queue-6.12/maintainers-add-entry-for-the-rust-alloc-module.patch queue-6.12/rust-alloc-fix-arraylayout-allocations.patch queue-6.12/drm-panic-prefer-eliding-lifetimes.patch