rust/kernel/uaccess.rs

Source file repositories/reference/linux-study-clean/rust/kernel/uaccess.rs

File Facts

System
Linux kernel
Corpus path
rust/kernel/uaccess.rs
Extension
.rs
Size
25017 bytes
Lines
665
Domain
Rust Kernel Layer
Bucket
Rust API Membrane
Inferred role
Rust Kernel Layer: implementation source
Status
source implementation candidate

Why This File Exists

Rust-side wrappers and abstractions around kernel C APIs, ownership contracts, allocation, synchronization, and module integration.

Dependency Surface

Detected Declarations

Annotated Snippet

pub fn reader_writer(self) -> (UserSliceReader, UserSliceWriter) {
        (
            UserSliceReader {
                ptr: self.ptr,
                length: self.length,
            },
            UserSliceWriter {
                ptr: self.ptr,
                length: self.length,
            },
        )
    }
}

/// A reader for [`UserSlice`].
///
/// Used to incrementally read from the user slice.
pub struct UserSliceReader {
    ptr: UserPtr,
    length: usize,
}

impl UserSliceReader {
    /// Skip the provided number of bytes.
    ///
    /// Returns an error if skipping more than the length of the buffer.
    pub fn skip(&mut self, num_skip: usize) -> Result {
        // Update `self.length` first since that's the fallible part of this operation.
        self.length = self.length.checked_sub(num_skip).ok_or(EFAULT)?;
        self.ptr = self.ptr.wrapping_byte_add(num_skip);
        Ok(())
    }

    /// Create a reader that can access the same range of data.
    ///
    /// Reading from the clone does not advance the current reader.
    ///
    /// The caller should take care to not introduce TOCTOU issues, as described in the
    /// documentation for [`UserSlice`].
    pub fn clone_reader(&self) -> UserSliceReader {
        UserSliceReader {
            ptr: self.ptr,
            length: self.length,
        }
    }

    /// Returns the number of bytes left to be read from this reader.
    ///
    /// Note that even reading less than this number of bytes may fail.
    pub fn len(&self) -> usize {
        self.length
    }

    /// Returns `true` if no data is available in the io buffer.
    pub fn is_empty(&self) -> bool {
        self.length == 0
    }

    /// Reads raw data from the user slice into a kernel buffer.
    ///
    /// For a version that uses `&mut [u8]`, please see [`UserSliceReader::read_slice`].
    ///
    /// Fails with [`EFAULT`] if the read happens on a bad address, or if the read goes out of
    /// bounds of this [`UserSliceReader`]. This call may modify `out` even if it returns an error.
    ///
    /// # Guarantees
    ///
    /// After a successful call to this method, all bytes in `out` are initialized.
    pub fn read_raw(&mut self, out: &mut [MaybeUninit<u8>]) -> Result {
        let len = out.len();
        let out_ptr = out.as_mut_ptr().cast::<c_void>();
        if len > self.length {
            return Err(EFAULT);
        }
        // SAFETY: `out_ptr` points into a mutable slice of length `len`, so we may write
        // that many bytes to it.
        let res = unsafe { bindings::copy_from_user(out_ptr, self.ptr.as_const_ptr(), len) };
        if res != 0 {
            return Err(EFAULT);
        }
        self.ptr = self.ptr.wrapping_byte_add(len);
        self.length -= len;
        Ok(())
    }

    /// Reads raw data from the user slice into a kernel buffer.
    ///
    /// Fails with [`EFAULT`] if the read happens on a bad address, or if the read goes out of
    /// bounds of this [`UserSliceReader`]. This call may modify `out` even if it returns an error.
    pub fn read_slice(&mut self, out: &mut [u8]) -> Result {

Annotation

Implementation Notes