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::{Allocator, Flags}, 9 bindings, 10 error::Result, 11 ffi::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::uaccess::{UserPtr, UserSlice}; 50 /// 51 /// fn bytes_add_one(uptr: UserPtr, len: usize) -> Result { 52 /// let (read, mut write) = UserSlice::new(uptr, len).reader_writer(); 53 /// 54 /// let mut buf = KVec::new(); 55 /// read.read_all(&mut buf, GFP_KERNEL)?; 56 /// 57 /// for b in &mut buf { 58 /// *b = b.wrapping_add(1); 59 /// } 60 /// 61 /// write.write_slice(&buf)?; 62 /// Ok(()) 63 /// } 64 /// ``` 65 /// 66 /// Example illustrating a TOCTOU (time-of-check to time-of-use) bug. 67 /// 68 /// ```no_run 69 /// use kernel::ffi::c_void; 70 /// use kernel::uaccess::{UserPtr, UserSlice}; 71 /// 72 /// /// Returns whether the data in this region is valid. 73 /// fn is_valid(uptr: UserPtr, len: usize) -> Result<bool> { 74 /// let read = UserSlice::new(uptr, len).reader(); 75 /// 76 /// let mut buf = KVec::new(); 77 /// read.read_all(&mut buf, GFP_KERNEL)?; 78 /// 79 /// todo!() 80 /// } 81 /// 82 /// /// Returns the bytes behind this user pointer if they are valid. 83 /// fn get_bytes_if_valid(uptr: UserPtr, len: usize) -> Result<KVec<u8>> { 84 /// if !is_valid(uptr, len)? { 85 /// return Err(EINVAL); 86 /// } 87 /// 88 /// let read = UserSlice::new(uptr, len).reader(); 89 /// 90 /// let mut buf = KVec::new(); 91 /// read.read_all(&mut buf, GFP_KERNEL)?; 92 /// 93 /// // THIS IS A BUG! The bytes could have changed since we checked them. 94 /// // 95 /// // To avoid this kind of bug, don't call `UserSlice::new` multiple 96 /// // times with the same address. 97 /// Ok(buf) 98 /// } 99 /// ``` 100 /// 101 /// [`std::io`]: https://doc.rust-lang.org/std/io/index.html 102 /// [`clone_reader`]: UserSliceReader::clone_reader 103 pub struct UserSlice { 104 ptr: UserPtr, 105 length: usize, 106 } 107 108 impl UserSlice { 109 /// Constructs a user slice from a raw pointer and a length in bytes. 110 /// 111 /// Constructing a [`UserSlice`] performs no checks on the provided address and length, it can 112 /// safely be constructed inside a kernel thread with no current userspace process. Reads and 113 /// writes wrap the kernel APIs `copy_from_user` and `copy_to_user`, which check the memory map 114 /// of the current process and enforce that the address range is within the user range (no 115 /// additional calls to `access_ok` are needed). Validity of the pointer is checked when you 116 /// attempt to read or write, not in the call to `UserSlice::new`. 117 /// 118 /// Callers must be careful to avoid time-of-check-time-of-use (TOCTOU) issues. The simplest way 119 /// is to create a single instance of [`UserSlice`] per user memory block as it reads each byte 120 /// at most once. new(ptr: UserPtr, length: usize) -> Self121 pub fn new(ptr: UserPtr, length: usize) -> Self { 122 UserSlice { ptr, length } 123 } 124 125 /// Reads the entirety of the user slice, appending it to the end of the provided buffer. 126 /// 127 /// Fails with [`EFAULT`] if the read happens on a bad address. read_all<A: Allocator>(self, buf: &mut Vec<u8, A>, flags: Flags) -> Result128 pub fn read_all<A: Allocator>(self, buf: &mut Vec<u8, A>, flags: Flags) -> Result { 129 self.reader().read_all(buf, flags) 130 } 131 132 /// Constructs a [`UserSliceReader`]. reader(self) -> UserSliceReader133 pub fn reader(self) -> UserSliceReader { 134 UserSliceReader { 135 ptr: self.ptr, 136 length: self.length, 137 } 138 } 139 140 /// Constructs a [`UserSliceWriter`]. writer(self) -> UserSliceWriter141 pub fn writer(self) -> UserSliceWriter { 142 UserSliceWriter { 143 ptr: self.ptr, 144 length: self.length, 145 } 146 } 147 148 /// Constructs both a [`UserSliceReader`] and a [`UserSliceWriter`]. 149 /// 150 /// Usually when this is used, you will first read the data, and then overwrite it afterwards. reader_writer(self) -> (UserSliceReader, UserSliceWriter)151 pub fn reader_writer(self) -> (UserSliceReader, UserSliceWriter) { 152 ( 153 UserSliceReader { 154 ptr: self.ptr, 155 length: self.length, 156 }, 157 UserSliceWriter { 158 ptr: self.ptr, 159 length: self.length, 160 }, 161 ) 162 } 163 } 164 165 /// A reader for [`UserSlice`]. 166 /// 167 /// Used to incrementally read from the user slice. 168 pub struct UserSliceReader { 169 ptr: UserPtr, 170 length: usize, 171 } 172 173 impl UserSliceReader { 174 /// Skip the provided number of bytes. 175 /// 176 /// Returns an error if skipping more than the length of the buffer. skip(&mut self, num_skip: usize) -> Result177 pub fn skip(&mut self, num_skip: usize) -> Result { 178 // Update `self.length` first since that's the fallible part of this operation. 179 self.length = self.length.checked_sub(num_skip).ok_or(EFAULT)?; 180 self.ptr = self.ptr.wrapping_add(num_skip); 181 Ok(()) 182 } 183 184 /// Create a reader that can access the same range of data. 185 /// 186 /// Reading from the clone does not advance the current reader. 187 /// 188 /// The caller should take care to not introduce TOCTOU issues, as described in the 189 /// documentation for [`UserSlice`]. clone_reader(&self) -> UserSliceReader190 pub fn clone_reader(&self) -> UserSliceReader { 191 UserSliceReader { 192 ptr: self.ptr, 193 length: self.length, 194 } 195 } 196 197 /// Returns the number of bytes left to be read from this reader. 198 /// 199 /// Note that even reading less than this number of bytes may fail. len(&self) -> usize200 pub fn len(&self) -> usize { 201 self.length 202 } 203 204 /// Returns `true` if no data is available in the io buffer. is_empty(&self) -> bool205 pub fn is_empty(&self) -> bool { 206 self.length == 0 207 } 208 209 /// Reads raw data from the user slice into a kernel buffer. 210 /// 211 /// For a version that uses `&mut [u8]`, please see [`UserSliceReader::read_slice`]. 212 /// 213 /// Fails with [`EFAULT`] if the read happens on a bad address, or if the read goes out of 214 /// bounds of this [`UserSliceReader`]. This call may modify `out` even if it returns an error. 215 /// 216 /// # Guarantees 217 /// 218 /// After a successful call to this method, all bytes in `out` are initialized. read_raw(&mut self, out: &mut [MaybeUninit<u8>]) -> Result219 pub fn read_raw(&mut self, out: &mut [MaybeUninit<u8>]) -> Result { 220 let len = out.len(); 221 let out_ptr = out.as_mut_ptr().cast::<c_void>(); 222 if len > self.length { 223 return Err(EFAULT); 224 } 225 // SAFETY: `out_ptr` points into a mutable slice of length `len`, so we may write 226 // that many bytes to it. 227 let res = unsafe { bindings::copy_from_user(out_ptr, self.ptr as *const c_void, len) }; 228 if res != 0 { 229 return Err(EFAULT); 230 } 231 self.ptr = self.ptr.wrapping_add(len); 232 self.length -= len; 233 Ok(()) 234 } 235 236 /// Reads raw data from the user slice into a kernel buffer. 237 /// 238 /// Fails with [`EFAULT`] if the read happens on a bad address, or if the read goes out of 239 /// bounds of this [`UserSliceReader`]. This call may modify `out` even if it returns an error. read_slice(&mut self, out: &mut [u8]) -> Result240 pub fn read_slice(&mut self, out: &mut [u8]) -> Result { 241 // SAFETY: The types are compatible and `read_raw` doesn't write uninitialized bytes to 242 // `out`. 243 let out = unsafe { &mut *(out as *mut [u8] as *mut [MaybeUninit<u8>]) }; 244 self.read_raw(out) 245 } 246 247 /// Reads a value of the specified type. 248 /// 249 /// Fails with [`EFAULT`] if the read happens on a bad address, or if the read goes out of 250 /// bounds of this [`UserSliceReader`]. read<T: FromBytes>(&mut self) -> Result<T>251 pub fn read<T: FromBytes>(&mut self) -> Result<T> { 252 let len = size_of::<T>(); 253 if len > self.length { 254 return Err(EFAULT); 255 } 256 let mut out: MaybeUninit<T> = MaybeUninit::uninit(); 257 // SAFETY: The local variable `out` is valid for writing `size_of::<T>()` bytes. 258 // 259 // By using the _copy_from_user variant, we skip the check_object_size check that verifies 260 // the kernel pointer. This mirrors the logic on the C side that skips the check when the 261 // length is a compile-time constant. 262 let res = unsafe { 263 bindings::_copy_from_user( 264 out.as_mut_ptr().cast::<c_void>(), 265 self.ptr as *const c_void, 266 len, 267 ) 268 }; 269 if res != 0 { 270 return Err(EFAULT); 271 } 272 self.ptr = self.ptr.wrapping_add(len); 273 self.length -= len; 274 // SAFETY: The read above has initialized all bytes in `out`, and since `T` implements 275 // `FromBytes`, any bit-pattern is a valid value for this type. 276 Ok(unsafe { out.assume_init() }) 277 } 278 279 /// Reads the entirety of the user slice, appending it to the end of the provided buffer. 280 /// 281 /// Fails with [`EFAULT`] if the read happens on a bad address. read_all<A: Allocator>(mut self, buf: &mut Vec<u8, A>, flags: Flags) -> Result282 pub fn read_all<A: Allocator>(mut self, buf: &mut Vec<u8, A>, flags: Flags) -> Result { 283 let len = self.length; 284 buf.reserve(len, flags)?; 285 286 // The call to `reserve` was successful, so the spare capacity is at least `len` bytes long. 287 self.read_raw(&mut buf.spare_capacity_mut()[..len])?; 288 289 // SAFETY: Since the call to `read_raw` was successful, so the next `len` bytes of the 290 // vector have been initialized. 291 unsafe { buf.inc_len(len) }; 292 Ok(()) 293 } 294 } 295 296 /// A writer for [`UserSlice`]. 297 /// 298 /// Used to incrementally write into the user slice. 299 pub struct UserSliceWriter { 300 ptr: UserPtr, 301 length: usize, 302 } 303 304 impl UserSliceWriter { 305 /// Returns the amount of space remaining in this buffer. 306 /// 307 /// Note that even writing less than this number of bytes may fail. len(&self) -> usize308 pub fn len(&self) -> usize { 309 self.length 310 } 311 312 /// Returns `true` if no more data can be written to this buffer. is_empty(&self) -> bool313 pub fn is_empty(&self) -> bool { 314 self.length == 0 315 } 316 317 /// Writes raw data to this user pointer from a kernel buffer. 318 /// 319 /// Fails with [`EFAULT`] if the write happens on a bad address, or if the write goes out of 320 /// bounds of this [`UserSliceWriter`]. This call may modify the associated userspace slice even 321 /// if it returns an error. write_slice(&mut self, data: &[u8]) -> Result322 pub fn write_slice(&mut self, data: &[u8]) -> Result { 323 let len = data.len(); 324 let data_ptr = data.as_ptr().cast::<c_void>(); 325 if len > self.length { 326 return Err(EFAULT); 327 } 328 // SAFETY: `data_ptr` points into an immutable slice of length `len`, so we may read 329 // that many bytes from it. 330 let res = unsafe { bindings::copy_to_user(self.ptr as *mut c_void, data_ptr, len) }; 331 if res != 0 { 332 return Err(EFAULT); 333 } 334 self.ptr = self.ptr.wrapping_add(len); 335 self.length -= len; 336 Ok(()) 337 } 338 339 /// Writes the provided Rust value to this userspace pointer. 340 /// 341 /// Fails with [`EFAULT`] if the write happens on a bad address, or if the write goes out of 342 /// bounds of this [`UserSliceWriter`]. This call may modify the associated userspace slice even 343 /// if it returns an error. write<T: AsBytes>(&mut self, value: &T) -> Result344 pub fn write<T: AsBytes>(&mut self, value: &T) -> Result { 345 let len = size_of::<T>(); 346 if len > self.length { 347 return Err(EFAULT); 348 } 349 // SAFETY: The reference points to a value of type `T`, so it is valid for reading 350 // `size_of::<T>()` bytes. 351 // 352 // By using the _copy_to_user variant, we skip the check_object_size check that verifies the 353 // kernel pointer. This mirrors the logic on the C side that skips the check when the length 354 // is a compile-time constant. 355 let res = unsafe { 356 bindings::_copy_to_user( 357 self.ptr as *mut c_void, 358 (value as *const T).cast::<c_void>(), 359 len, 360 ) 361 }; 362 if res != 0 { 363 return Err(EFAULT); 364 } 365 self.ptr = self.ptr.wrapping_add(len); 366 self.length -= len; 367 Ok(()) 368 } 369 } 370