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