1 // SPDX-License-Identifier: GPL-2.0 2 3 //! Slices to user space memory regions. 4 //! 5 //! C header: [`include/linux/uaccess.h`](srctree/include/linux/uaccess.h) 6 7 use crate::{ 8 alloc::Flags, 9 bindings, 10 error::Result, 11 prelude::*, 12 types::{AsBytes, FromBytes}, 13 }; 14 use alloc::vec::Vec; 15 use core::ffi::{c_ulong, c_void}; 16 use core::mem::{size_of, MaybeUninit}; 17 18 /// The type used for userspace addresses. 19 pub type UserPtr = usize; 20 21 /// A pointer to an area in userspace memory, which can be either read-only or read-write. 22 /// 23 /// All methods on this struct are safe: attempting to read or write on bad addresses (either out of 24 /// the bound of the slice or unmapped addresses) will return [`EFAULT`]. Concurrent access, 25 /// *including data races to/from userspace memory*, is permitted, because fundamentally another 26 /// userspace thread/process could always be modifying memory at the same time (in the same way that 27 /// userspace Rust's [`std::io`] permits data races with the contents of files on disk). In the 28 /// presence of a race, the exact byte values read/written are unspecified but the operation is 29 /// well-defined. Kernelspace code should validate its copy of data after completing a read, and not 30 /// expect that multiple reads of the same address will return the same value. 31 /// 32 /// These APIs are designed to make it difficult to accidentally write TOCTOU (time-of-check to 33 /// time-of-use) bugs. Every time a memory location is read, the reader's position is advanced by 34 /// the read length and the next read will start from there. This helps prevent accidentally reading 35 /// the same location twice and causing a TOCTOU bug. 36 /// 37 /// Creating a [`UserSliceReader`] and/or [`UserSliceWriter`] consumes the `UserSlice`, helping 38 /// ensure that there aren't multiple readers or writers to the same location. 39 /// 40 /// If double-fetching a memory location is necessary for some reason, then that is done by creating 41 /// multiple readers to the same memory location, e.g. using [`clone_reader`]. 42 /// 43 /// # Examples 44 /// 45 /// Takes a region of userspace memory from the current process, and modify it by adding one to 46 /// every byte in the region. 47 /// 48 /// ```no_run 49 /// use alloc::vec::Vec; 50 /// use core::ffi::c_void; 51 /// use kernel::error::Result; 52 /// use kernel::uaccess::{UserPtr, UserSlice}; 53 /// 54 /// fn bytes_add_one(uptr: UserPtr, len: usize) -> Result<()> { 55 /// let (read, mut write) = UserSlice::new(uptr, len).reader_writer(); 56 /// 57 /// let mut buf = Vec::new(); 58 /// read.read_all(&mut buf, GFP_KERNEL)?; 59 /// 60 /// for b in &mut buf { 61 /// *b = b.wrapping_add(1); 62 /// } 63 /// 64 /// write.write_slice(&buf)?; 65 /// Ok(()) 66 /// } 67 /// ``` 68 /// 69 /// Example illustrating a TOCTOU (time-of-check to time-of-use) bug. 70 /// 71 /// ```no_run 72 /// use alloc::vec::Vec; 73 /// use core::ffi::c_void; 74 /// use kernel::error::{code::EINVAL, Result}; 75 /// use kernel::uaccess::{UserPtr, UserSlice}; 76 /// 77 /// /// Returns whether the data in this region is valid. 78 /// fn is_valid(uptr: UserPtr, len: usize) -> Result<bool> { 79 /// let read = UserSlice::new(uptr, len).reader(); 80 /// 81 /// let mut buf = Vec::new(); 82 /// read.read_all(&mut buf, GFP_KERNEL)?; 83 /// 84 /// todo!() 85 /// } 86 /// 87 /// /// Returns the bytes behind this user pointer if they are valid. 88 /// fn get_bytes_if_valid(uptr: UserPtr, len: usize) -> Result<Vec<u8>> { 89 /// if !is_valid(uptr, len)? { 90 /// return Err(EINVAL); 91 /// } 92 /// 93 /// let read = UserSlice::new(uptr, len).reader(); 94 /// 95 /// let mut buf = Vec::new(); 96 /// read.read_all(&mut buf, GFP_KERNEL)?; 97 /// 98 /// // THIS IS A BUG! The bytes could have changed since we checked them. 99 /// // 100 /// // To avoid this kind of bug, don't call `UserSlice::new` multiple 101 /// // times with the same address. 102 /// Ok(buf) 103 /// } 104 /// ``` 105 /// 106 /// [`std::io`]: https://doc.rust-lang.org/std/io/index.html 107 /// [`clone_reader`]: UserSliceReader::clone_reader 108 pub struct UserSlice { 109 ptr: UserPtr, 110 length: usize, 111 } 112 113 impl UserSlice { 114 /// Constructs a user slice from a raw pointer and a length in bytes. 115 /// 116 /// Constructing a [`UserSlice`] performs no checks on the provided address and length, it can 117 /// safely be constructed inside a kernel thread with no current userspace process. Reads and 118 /// writes wrap the kernel APIs `copy_from_user` and `copy_to_user`, which check the memory map 119 /// of the current process and enforce that the address range is within the user range (no 120 /// additional calls to `access_ok` are needed). Validity of the pointer is checked when you 121 /// attempt to read or write, not in the call to `UserSlice::new`. 122 /// 123 /// Callers must be careful to avoid time-of-check-time-of-use (TOCTOU) issues. The simplest way 124 /// is to create a single instance of [`UserSlice`] per user memory block as it reads each byte 125 /// at most once. 126 pub fn new(ptr: UserPtr, length: usize) -> Self { 127 UserSlice { ptr, length } 128 } 129 130 /// Reads the entirety of the user slice, appending it to the end of the provided buffer. 131 /// 132 /// Fails with [`EFAULT`] if the read happens on a bad address. 133 pub fn read_all(self, buf: &mut Vec<u8>, flags: Flags) -> Result { 134 self.reader().read_all(buf, flags) 135 } 136 137 /// Constructs a [`UserSliceReader`]. 138 pub fn reader(self) -> UserSliceReader { 139 UserSliceReader { 140 ptr: self.ptr, 141 length: self.length, 142 } 143 } 144 145 /// Constructs a [`UserSliceWriter`]. 146 pub fn writer(self) -> UserSliceWriter { 147 UserSliceWriter { 148 ptr: self.ptr, 149 length: self.length, 150 } 151 } 152 153 /// Constructs both a [`UserSliceReader`] and a [`UserSliceWriter`]. 154 /// 155 /// Usually when this is used, you will first read the data, and then overwrite it afterwards. 156 pub fn reader_writer(self) -> (UserSliceReader, UserSliceWriter) { 157 ( 158 UserSliceReader { 159 ptr: self.ptr, 160 length: self.length, 161 }, 162 UserSliceWriter { 163 ptr: self.ptr, 164 length: self.length, 165 }, 166 ) 167 } 168 } 169 170 /// A reader for [`UserSlice`]. 171 /// 172 /// Used to incrementally read from the user slice. 173 pub struct UserSliceReader { 174 ptr: UserPtr, 175 length: usize, 176 } 177 178 impl UserSliceReader { 179 /// Skip the provided number of bytes. 180 /// 181 /// Returns an error if skipping more than the length of the buffer. 182 pub fn skip(&mut self, num_skip: usize) -> Result { 183 // Update `self.length` first since that's the fallible part of this operation. 184 self.length = self.length.checked_sub(num_skip).ok_or(EFAULT)?; 185 self.ptr = self.ptr.wrapping_add(num_skip); 186 Ok(()) 187 } 188 189 /// Create a reader that can access the same range of data. 190 /// 191 /// Reading from the clone does not advance the current reader. 192 /// 193 /// The caller should take care to not introduce TOCTOU issues, as described in the 194 /// documentation for [`UserSlice`]. 195 pub fn clone_reader(&self) -> UserSliceReader { 196 UserSliceReader { 197 ptr: self.ptr, 198 length: self.length, 199 } 200 } 201 202 /// Returns the number of bytes left to be read from this reader. 203 /// 204 /// Note that even reading less than this number of bytes may fail. 205 pub fn len(&self) -> usize { 206 self.length 207 } 208 209 /// Returns `true` if no data is available in the io buffer. 210 pub fn is_empty(&self) -> bool { 211 self.length == 0 212 } 213 214 /// Reads raw data from the user slice into a kernel buffer. 215 /// 216 /// For a version that uses `&mut [u8]`, please see [`UserSliceReader::read_slice`]. 217 /// 218 /// Fails with [`EFAULT`] if the read happens on a bad address, or if the read goes out of 219 /// bounds of this [`UserSliceReader`]. This call may modify `out` even if it returns an error. 220 /// 221 /// # Guarantees 222 /// 223 /// After a successful call to this method, all bytes in `out` are initialized. 224 pub fn read_raw(&mut self, out: &mut [MaybeUninit<u8>]) -> Result { 225 let len = out.len(); 226 let out_ptr = out.as_mut_ptr().cast::<c_void>(); 227 if len > self.length { 228 return Err(EFAULT); 229 } 230 let Ok(len_ulong) = c_ulong::try_from(len) else { 231 return Err(EFAULT); 232 }; 233 // SAFETY: `out_ptr` points into a mutable slice of length `len_ulong`, so we may write 234 // that many bytes to it. 235 let res = 236 unsafe { bindings::copy_from_user(out_ptr, self.ptr as *const c_void, len_ulong) }; 237 if res != 0 { 238 return Err(EFAULT); 239 } 240 self.ptr = self.ptr.wrapping_add(len); 241 self.length -= len; 242 Ok(()) 243 } 244 245 /// Reads raw data from the user slice into a kernel buffer. 246 /// 247 /// Fails with [`EFAULT`] if the read happens on a bad address, or if the read goes out of 248 /// bounds of this [`UserSliceReader`]. This call may modify `out` even if it returns an error. 249 pub fn read_slice(&mut self, out: &mut [u8]) -> Result { 250 // SAFETY: The types are compatible and `read_raw` doesn't write uninitialized bytes to 251 // `out`. 252 let out = unsafe { &mut *(out as *mut [u8] as *mut [MaybeUninit<u8>]) }; 253 self.read_raw(out) 254 } 255 256 /// Reads a value of the specified type. 257 /// 258 /// Fails with [`EFAULT`] if the read happens on a bad address, or if the read goes out of 259 /// bounds of this [`UserSliceReader`]. 260 pub fn read<T: FromBytes>(&mut self) -> Result<T> { 261 let len = size_of::<T>(); 262 if len > self.length { 263 return Err(EFAULT); 264 } 265 let Ok(len_ulong) = c_ulong::try_from(len) else { 266 return Err(EFAULT); 267 }; 268 let mut out: MaybeUninit<T> = MaybeUninit::uninit(); 269 // SAFETY: The local variable `out` is valid for writing `size_of::<T>()` bytes. 270 // 271 // By using the _copy_from_user variant, we skip the check_object_size check that verifies 272 // the kernel pointer. This mirrors the logic on the C side that skips the check when the 273 // length is a compile-time constant. 274 let res = unsafe { 275 bindings::_copy_from_user( 276 out.as_mut_ptr().cast::<c_void>(), 277 self.ptr as *const c_void, 278 len_ulong, 279 ) 280 }; 281 if res != 0 { 282 return Err(EFAULT); 283 } 284 self.ptr = self.ptr.wrapping_add(len); 285 self.length -= len; 286 // SAFETY: The read above has initialized all bytes in `out`, and since `T` implements 287 // `FromBytes`, any bit-pattern is a valid value for this type. 288 Ok(unsafe { out.assume_init() }) 289 } 290 291 /// Reads the entirety of the user slice, appending it to the end of the provided buffer. 292 /// 293 /// Fails with [`EFAULT`] if the read happens on a bad address. 294 pub fn read_all(mut self, buf: &mut Vec<u8>, flags: Flags) -> Result { 295 let len = self.length; 296 VecExt::<u8>::reserve(buf, len, flags)?; 297 298 // The call to `try_reserve` was successful, so the spare capacity is at least `len` bytes 299 // long. 300 self.read_raw(&mut buf.spare_capacity_mut()[..len])?; 301 302 // SAFETY: Since the call to `read_raw` was successful, so the next `len` bytes of the 303 // vector have been initialized. 304 unsafe { buf.set_len(buf.len() + len) }; 305 Ok(()) 306 } 307 } 308 309 /// A writer for [`UserSlice`]. 310 /// 311 /// Used to incrementally write into the user slice. 312 pub struct UserSliceWriter { 313 ptr: UserPtr, 314 length: usize, 315 } 316 317 impl UserSliceWriter { 318 /// Returns the amount of space remaining in this buffer. 319 /// 320 /// Note that even writing less than this number of bytes may fail. 321 pub fn len(&self) -> usize { 322 self.length 323 } 324 325 /// Returns `true` if no more data can be written to this buffer. 326 pub fn is_empty(&self) -> bool { 327 self.length == 0 328 } 329 330 /// Writes raw data to this user pointer from a kernel buffer. 331 /// 332 /// Fails with [`EFAULT`] if the write happens on a bad address, or if the write goes out of 333 /// bounds of this [`UserSliceWriter`]. This call may modify the associated userspace slice even 334 /// if it returns an error. 335 pub fn write_slice(&mut self, data: &[u8]) -> Result { 336 let len = data.len(); 337 let data_ptr = data.as_ptr().cast::<c_void>(); 338 if len > self.length { 339 return Err(EFAULT); 340 } 341 let Ok(len_ulong) = c_ulong::try_from(len) else { 342 return Err(EFAULT); 343 }; 344 // SAFETY: `data_ptr` points into an immutable slice of length `len_ulong`, so we may read 345 // that many bytes from it. 346 let res = unsafe { bindings::copy_to_user(self.ptr as *mut c_void, data_ptr, len_ulong) }; 347 if res != 0 { 348 return Err(EFAULT); 349 } 350 self.ptr = self.ptr.wrapping_add(len); 351 self.length -= len; 352 Ok(()) 353 } 354 355 /// Writes the provided Rust value to this userspace pointer. 356 /// 357 /// Fails with [`EFAULT`] if the write happens on a bad address, or if the write goes out of 358 /// bounds of this [`UserSliceWriter`]. This call may modify the associated userspace slice even 359 /// if it returns an error. 360 pub fn write<T: AsBytes>(&mut self, value: &T) -> Result { 361 let len = size_of::<T>(); 362 if len > self.length { 363 return Err(EFAULT); 364 } 365 let Ok(len_ulong) = c_ulong::try_from(len) else { 366 return Err(EFAULT); 367 }; 368 // SAFETY: The reference points to a value of type `T`, so it is valid for reading 369 // `size_of::<T>()` bytes. 370 // 371 // By using the _copy_to_user variant, we skip the check_object_size check that verifies the 372 // kernel pointer. This mirrors the logic on the C side that skips the check when the length 373 // is a compile-time constant. 374 let res = unsafe { 375 bindings::_copy_to_user( 376 self.ptr as *mut c_void, 377 (value as *const T).cast::<c_void>(), 378 len_ulong, 379 ) 380 }; 381 if res != 0 { 382 return Err(EFAULT); 383 } 384 self.ptr = self.ptr.wrapping_add(len); 385 self.length -= len; 386 Ok(()) 387 } 388 }
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.