UserConstPtr API
Relevant source files
This document provides a comprehensive reference for the UserConstPtr<T>
type, which enables safe read-only access to user-space memory from kernel code. For information about mutable access to user memory, see UserPtr API.
Overview
UserConstPtr<T>
is a generic wrapper around a raw const pointer (*const T
) that provides memory-safe operations for reading data from user space. It implements safety checks that prevent common issues like null pointer dereferences, buffer overflows, and illegal memory accesses.
classDiagram class UserConstPtr~T~ { +*const T pointer +const ACCESS_FLAGS: MappingFlags +address() VirtAddr +as_ptr() *const T +cast~U~() UserConstPtr~U~ +is_null() bool +nullable() Option~Self~ +get() LinuxResult~&T~ +get_as_slice() LinuxResult~&[T]~ +get_as_null_terminated() LinuxResult~&[T]~ } class UserConstPtr_cchar { +get_as_str() LinuxResult~&str~ } UserConstPtr_cchar --|> UserConstPtr : "Specializedimplementation"
Sources: src/lib.rs(L219 - L303)
Memory Safety Architecture
The UserConstPtr<T>
type is part of a comprehensive memory safety system that prevents the kernel from crashing when accessing potentially invalid user memory. Unlike raw pointers, UserConstPtr<T>
operations perform several safety checks before accessing user memory:
flowchart TD A["UserConstPtr.get()"] B["check_region_with()"] C["Is pointeraligned?"] D["Error: EFAULT"] E["Valid memoryaccess rights?"] F["Populate page tables"] G["Page tablespopulated?"] H["Error: ENOMEM"] I["Set ACCESSING_USER_MEM flag"] J["Access memory"] K["Clear ACCESSING_USER_MEM flag"] L["Return reference"] A --> B B --> C C --> D C --> E E --> D E --> F F --> G G --> H G --> I I --> J J --> K K --> L
Sources: src/lib.rs(L31 - L54) src/lib.rs(L258 - L266)
Type Definition
UserConstPtr<T>
is defined as a transparent wrapper around a raw const pointer:
#[repr(transparent)]
pub struct UserConstPtr<T>(*const T);
The #[repr(transparent)]
attribute ensures that UserConstPtr<T>
has the same memory layout as *const T
, making it efficient for passing across FFI boundaries.
Sources: src/lib.rs(L219 - L221)
Constants
Constant | Type | Description |
---|---|---|
ACCESS_FLAGS | MappingFlags | Specifies required memory access flags (READ) for user memory regions |
Sources: src/lib.rs(L227 - L228)
Basic Methods
Conversion and Type Manipulation
Method | Signature | Description |
---|---|---|
From | fn from(value: usize) -> Self | Creates aUserConstPtr |
address | fn address(&self) -> VirtAddr | Returns the virtual address of the pointer |
as_ptr | unsafe fn as_ptr(&self) -> *const T | Returns the underlying raw pointer (unsafe) |
cast | fn cast(self) -> UserConstPtr | Casts the pointer to a different type |
Sources: src/lib.rs(L221 - L243)
Null Checking
Method | Signature | Description |
---|---|---|
is_null | fn is_null(&self) -> bool | Checks if the pointer is null |
nullable | fn nullable(self) -> Option | Converts toNoneif null, orSome(self)otherwise |
Sources: src/lib.rs(L245 - L253)
Memory Access Methods
Single Value Access
#![allow(unused)] fn main() { fn get(&self, aspace: impl AddrSpaceProvider) -> LinuxResult<&T> }
Safely retrieves a reference to the value pointed to by UserConstPtr<T>
:
- Validates memory alignment
- Checks user memory access permissions
- Populates page tables if necessary
- Returns a reference or
EFAULT
error if access failed
Sources: src/lib.rs(L258 - L266)
Slice Access
#![allow(unused)] fn main() { fn get_as_slice(&self, aspace: impl AddrSpaceProvider, length: usize) -> LinuxResult<&[T]> }
Safely retrieves a slice of values:
- Validates memory region for the entire slice
- Verifies alignment and access permissions
- Returns a slice reference or error if access failed
Sources: src/lib.rs(L269 - L277)
Null-Terminated Data
#![allow(unused)] fn main() { fn get_as_null_terminated(&self, aspace: impl AddrSpaceProvider) -> LinuxResult<&[T]> where T: Eq + Default, }
Retrieves a slice of values terminated by a null value (default value of type T
):
- Scans memory until it finds a null value
- Checks access permissions page-by-page during scan
- Returns a slice that includes all values up to (but not including) the null terminator
Sources: src/lib.rs(L282 - L291)
String-Specific Operations
UserConstPtr<c_char>
has an additional method for safely retrieving strings from user space:
#![allow(unused)] fn main() { fn get_as_str(&self, aspace: impl AddrSpaceProvider) -> LinuxResult<&'static str> }
This method:
- Gets the null-terminated array using
get_as_null_terminated
- Transmutes the char array to bytes
- Validates that the bytes form valid UTF-8
- Returns a string reference or
EILSEQ
error if invalid UTF-8
Sources: src/lib.rs(L294 - L302)
Memory Access Flow
The following diagram illustrates the complete flow of operations when accessing user memory with UserConstPtr
:
sequenceDiagram participant KernelCode as "Kernel Code" participant UserConstPtrT as "UserConstPtr<T>" participant AddrSpaceProvider as "AddrSpaceProvider" participant check_region as "check_region" participant UserMemory as "User Memory" KernelCode ->> UserConstPtrT: Call get/get_as_slice/etc. UserConstPtrT ->> AddrSpaceProvider: with_addr_space() AddrSpaceProvider ->> check_region: check_region() check_region ->> check_region: Check alignment check_region ->> check_region: Check access permissions check_region ->> check_region: Populate page tables alt Access Allowed check_region ->> AddrSpaceProvider: Ok(()) AddrSpaceProvider ->> UserConstPtrT: Ok(()) UserConstPtrT ->> UserConstPtrT: Set ACCESSING_USER_MEM = true UserConstPtrT ->> UserMemory: Read memory UserConstPtrT ->> UserConstPtrT: Set ACCESSING_USER_MEM = false UserConstPtrT ->> KernelCode: Return reference else Access Denied check_region ->> AddrSpaceProvider: Err(EFAULT) AddrSpaceProvider ->> UserConstPtrT: Err(EFAULT) UserConstPtrT ->> KernelCode: Return error end
Sources: src/lib.rs(L22 - L29) src/lib.rs(L31 - L54) src/lib.rs(L258 - L266)
Usage Example
Here's a conceptual example of using UserConstPtr
:
- Receive a user address as a
usize
- Convert it to a
UserConstPtr<T>
- Check if it's null
- Access the user memory safely
- Handle any errors appropriately
Differences from UserPtr
While UserPtr<T>
provides mutable access with both read and write permissions, UserConstPtr<T>
is specifically designed for read-only access:
Feature | UserPtr | UserConstPtr |
---|---|---|
Underlying type | *mut T | *const T |
Access flags | `READ | WRITE` |
Reference type | &mut T | &T |
Usage | Reading and writing | Reading only |
Sources: src/lib.rs(L137) src/lib.rs(L227 - L228)
Thread Safety
UserConstPtr<T>
operations use a thread-local variable ACCESSING_USER_MEM
that informs the page fault handler that a page fault during memory access should be handled rather than causing a kernel panic. This flag is automatically set and cleared during memory access operations.