xref: /linux/rust/kernel/uaccess.rs (revision 38f7e5450ebfc6f2e046a249a3f629ea7bec8c31)
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     dma::Coherent,
11     error::Result,
12     ffi::{c_char, c_void},
13     fs::file,
14     prelude::*,
15     transmute::{AsBytes, FromBytes},
16 };
17 use core::mem::{size_of, MaybeUninit};
18 
19 /// A pointer into userspace.
20 ///
21 /// This is the Rust equivalent to C pointers tagged with `__user`.
22 #[repr(transparent)]
23 #[derive(Copy, Clone)]
24 pub struct UserPtr(*mut c_void);
25 
26 impl UserPtr {
27     /// Create a `UserPtr` from an integer representing the userspace address.
28     #[inline]
29     pub fn from_addr(addr: usize) -> Self {
30         Self(addr as *mut c_void)
31     }
32 
33     /// Create a `UserPtr` from a pointer representing the userspace address.
34     #[inline]
35     pub fn from_ptr(addr: *mut c_void) -> Self {
36         Self(addr)
37     }
38 
39     /// Cast this userspace pointer to a raw const void pointer.
40     ///
41     /// It is up to the caller to use the returned pointer correctly.
42     #[inline]
43     pub fn as_const_ptr(self) -> *const c_void {
44         self.0
45     }
46 
47     /// Cast this userspace pointer to a raw mutable void pointer.
48     ///
49     /// It is up to the caller to use the returned pointer correctly.
50     #[inline]
51     pub fn as_mut_ptr(self) -> *mut c_void {
52         self.0
53     }
54 
55     /// Increment this user pointer by `add` bytes.
56     ///
57     /// This addition is wrapping, so wrapping around the address space does not result in a panic
58     /// even if `CONFIG_RUST_OVERFLOW_CHECKS` is enabled.
59     #[inline]
60     pub fn wrapping_byte_add(self, add: usize) -> UserPtr {
61         UserPtr(self.0.wrapping_byte_add(add))
62     }
63 }
64 
65 /// A pointer to an area in userspace memory, which can be either read-only or read-write.
66 ///
67 /// All methods on this struct are safe: attempting to read or write on bad addresses (either out of
68 /// the bound of the slice or unmapped addresses) will return [`EFAULT`]. Concurrent access,
69 /// *including data races to/from userspace memory*, is permitted, because fundamentally another
70 /// userspace thread/process could always be modifying memory at the same time (in the same way that
71 /// userspace Rust's [`std::io`] permits data races with the contents of files on disk). In the
72 /// presence of a race, the exact byte values read/written are unspecified but the operation is
73 /// well-defined. Kernelspace code should validate its copy of data after completing a read, and not
74 /// expect that multiple reads of the same address will return the same value.
75 ///
76 /// These APIs are designed to make it difficult to accidentally write TOCTOU (time-of-check to
77 /// time-of-use) bugs. Every time a memory location is read, the reader's position is advanced by
78 /// the read length and the next read will start from there. This helps prevent accidentally reading
79 /// the same location twice and causing a TOCTOU bug.
80 ///
81 /// Creating a [`UserSliceReader`] and/or [`UserSliceWriter`] consumes the `UserSlice`, helping
82 /// ensure that there aren't multiple readers or writers to the same location.
83 ///
84 /// If double-fetching a memory location is necessary for some reason, then that is done by creating
85 /// multiple readers to the same memory location, e.g. using [`clone_reader`].
86 ///
87 /// # Examples
88 ///
89 /// Takes a region of userspace memory from the current process, and modify it by adding one to
90 /// every byte in the region.
91 ///
92 /// ```no_run
93 /// use kernel::ffi::c_void;
94 /// use kernel::uaccess::{UserPtr, UserSlice};
95 ///
96 /// fn bytes_add_one(uptr: UserPtr, len: usize) -> Result {
97 ///     let (read, mut write) = UserSlice::new(uptr, len).reader_writer();
98 ///
99 ///     let mut buf = KVec::new();
100 ///     read.read_all(&mut buf, GFP_KERNEL)?;
101 ///
102 ///     for b in &mut buf {
103 ///         *b = b.wrapping_add(1);
104 ///     }
105 ///
106 ///     write.write_slice(&buf)?;
107 ///     Ok(())
108 /// }
109 /// ```
110 ///
111 /// Example illustrating a TOCTOU (time-of-check to time-of-use) bug.
112 ///
113 /// ```no_run
114 /// use kernel::ffi::c_void;
115 /// use kernel::uaccess::{UserPtr, UserSlice};
116 ///
117 /// /// Returns whether the data in this region is valid.
118 /// fn is_valid(uptr: UserPtr, len: usize) -> Result<bool> {
119 ///     let read = UserSlice::new(uptr, len).reader();
120 ///
121 ///     let mut buf = KVec::new();
122 ///     read.read_all(&mut buf, GFP_KERNEL)?;
123 ///
124 ///     todo!()
125 /// }
126 ///
127 /// /// Returns the bytes behind this user pointer if they are valid.
128 /// fn get_bytes_if_valid(uptr: UserPtr, len: usize) -> Result<KVec<u8>> {
129 ///     if !is_valid(uptr, len)? {
130 ///         return Err(EINVAL);
131 ///     }
132 ///
133 ///     let read = UserSlice::new(uptr, len).reader();
134 ///
135 ///     let mut buf = KVec::new();
136 ///     read.read_all(&mut buf, GFP_KERNEL)?;
137 ///
138 ///     // THIS IS A BUG! The bytes could have changed since we checked them.
139 ///     //
140 ///     // To avoid this kind of bug, don't call `UserSlice::new` multiple
141 ///     // times with the same address.
142 ///     Ok(buf)
143 /// }
144 /// ```
145 ///
146 /// [`std::io`]: https://doc.rust-lang.org/std/io/index.html
147 /// [`clone_reader`]: UserSliceReader::clone_reader
148 pub struct UserSlice {
149     ptr: UserPtr,
150     length: usize,
151 }
152 
153 impl UserSlice {
154     /// Constructs a user slice from a raw pointer and a length in bytes.
155     ///
156     /// Constructing a [`UserSlice`] performs no checks on the provided address and length, it can
157     /// safely be constructed inside a kernel thread with no current userspace process. Reads and
158     /// writes wrap the kernel APIs `copy_from_user` and `copy_to_user`, which check the memory map
159     /// of the current process and enforce that the address range is within the user range (no
160     /// additional calls to `access_ok` are needed). Validity of the pointer is checked when you
161     /// attempt to read or write, not in the call to `UserSlice::new`.
162     ///
163     /// Callers must be careful to avoid time-of-check-time-of-use (TOCTOU) issues. The simplest way
164     /// is to create a single instance of [`UserSlice`] per user memory block as it reads each byte
165     /// at most once.
166     pub fn new(ptr: UserPtr, length: usize) -> Self {
167         UserSlice { ptr, length }
168     }
169 
170     /// Reads the entirety of the user slice, appending it to the end of the provided buffer.
171     ///
172     /// Fails with [`EFAULT`] if the read happens on a bad address.
173     pub fn read_all<A: Allocator>(self, buf: &mut Vec<u8, A>, flags: Flags) -> Result {
174         self.reader().read_all(buf, flags)
175     }
176 
177     /// Constructs a [`UserSliceReader`].
178     pub fn reader(self) -> UserSliceReader {
179         UserSliceReader {
180             ptr: self.ptr,
181             length: self.length,
182         }
183     }
184 
185     /// Constructs a [`UserSliceWriter`].
186     pub fn writer(self) -> UserSliceWriter {
187         UserSliceWriter {
188             ptr: self.ptr,
189             length: self.length,
190         }
191     }
192 
193     /// Constructs both a [`UserSliceReader`] and a [`UserSliceWriter`].
194     ///
195     /// Usually when this is used, you will first read the data, and then overwrite it afterwards.
196     pub fn reader_writer(self) -> (UserSliceReader, UserSliceWriter) {
197         (
198             UserSliceReader {
199                 ptr: self.ptr,
200                 length: self.length,
201             },
202             UserSliceWriter {
203                 ptr: self.ptr,
204                 length: self.length,
205             },
206         )
207     }
208 }
209 
210 /// A reader for [`UserSlice`].
211 ///
212 /// Used to incrementally read from the user slice.
213 pub struct UserSliceReader {
214     ptr: UserPtr,
215     length: usize,
216 }
217 
218 impl UserSliceReader {
219     /// Skip the provided number of bytes.
220     ///
221     /// Returns an error if skipping more than the length of the buffer.
222     pub fn skip(&mut self, num_skip: usize) -> Result {
223         // Update `self.length` first since that's the fallible part of this operation.
224         self.length = self.length.checked_sub(num_skip).ok_or(EFAULT)?;
225         self.ptr = self.ptr.wrapping_byte_add(num_skip);
226         Ok(())
227     }
228 
229     /// Create a reader that can access the same range of data.
230     ///
231     /// Reading from the clone does not advance the current reader.
232     ///
233     /// The caller should take care to not introduce TOCTOU issues, as described in the
234     /// documentation for [`UserSlice`].
235     pub fn clone_reader(&self) -> UserSliceReader {
236         UserSliceReader {
237             ptr: self.ptr,
238             length: self.length,
239         }
240     }
241 
242     /// Returns the number of bytes left to be read from this reader.
243     ///
244     /// Note that even reading less than this number of bytes may fail.
245     pub fn len(&self) -> usize {
246         self.length
247     }
248 
249     /// Returns `true` if no data is available in the io buffer.
250     pub fn is_empty(&self) -> bool {
251         self.length == 0
252     }
253 
254     /// Reads raw data from the user slice into a kernel buffer.
255     ///
256     /// For a version that uses `&mut [u8]`, please see [`UserSliceReader::read_slice`].
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`]. This call may modify `out` even if it returns an error.
260     ///
261     /// # Guarantees
262     ///
263     /// After a successful call to this method, all bytes in `out` are initialized.
264     pub fn read_raw(&mut self, out: &mut [MaybeUninit<u8>]) -> Result {
265         let len = out.len();
266         let out_ptr = out.as_mut_ptr().cast::<c_void>();
267         if len > self.length {
268             return Err(EFAULT);
269         }
270         // SAFETY: `out_ptr` points into a mutable slice of length `len`, so we may write
271         // that many bytes to it.
272         let res = unsafe { bindings::copy_from_user(out_ptr, self.ptr.as_const_ptr(), len) };
273         if res != 0 {
274             return Err(EFAULT);
275         }
276         self.ptr = self.ptr.wrapping_byte_add(len);
277         self.length -= len;
278         Ok(())
279     }
280 
281     /// Reads raw data from the user slice into a kernel buffer.
282     ///
283     /// Fails with [`EFAULT`] if the read happens on a bad address, or if the read goes out of
284     /// bounds of this [`UserSliceReader`]. This call may modify `out` even if it returns an error.
285     pub fn read_slice(&mut self, out: &mut [u8]) -> Result {
286         // SAFETY: The types are compatible and `read_raw` doesn't write uninitialized bytes to
287         // `out`.
288         let out = unsafe { &mut *(core::ptr::from_mut(out) as *mut [MaybeUninit<u8>]) };
289         self.read_raw(out)
290     }
291 
292     /// Reads raw data from the user slice into a kernel buffer partially.
293     ///
294     /// This is the same as [`Self::read_slice`] but considers the given `offset` into `out` and
295     /// truncates the read to the boundaries of `self` and `out`.
296     ///
297     /// On success, returns the number of bytes read.
298     pub fn read_slice_partial(&mut self, out: &mut [u8], offset: usize) -> Result<usize> {
299         let end = offset.saturating_add(self.len()).min(out.len());
300 
301         let Some(dst) = out.get_mut(offset..end) else {
302             return Ok(0);
303         };
304 
305         self.read_slice(dst)?;
306         Ok(dst.len())
307     }
308 
309     /// Reads raw data from the user slice into a kernel buffer partially.
310     ///
311     /// This is the same as [`Self::read_slice_partial`] but updates the given [`file::Offset`] by
312     /// the number of bytes read.
313     ///
314     /// This is equivalent to C's `simple_write_to_buffer()`.
315     ///
316     /// On success, returns the number of bytes read.
317     pub fn read_slice_file(&mut self, out: &mut [u8], offset: &mut file::Offset) -> Result<usize> {
318         if offset.is_negative() {
319             return Err(EINVAL);
320         }
321 
322         let Ok(offset_index) = (*offset).try_into() else {
323             return Ok(0);
324         };
325 
326         let read = self.read_slice_partial(out, offset_index)?;
327 
328         // OVERFLOW: `offset + read <= data.len() <= isize::MAX <= Offset::MAX`
329         *offset += read as i64;
330 
331         Ok(read)
332     }
333 
334     /// Reads a value of the specified type.
335     ///
336     /// Fails with [`EFAULT`] if the read happens on a bad address, or if the read goes out of
337     /// bounds of this [`UserSliceReader`].
338     pub fn read<T: FromBytes>(&mut self) -> Result<T> {
339         let len = size_of::<T>();
340         if len > self.length {
341             return Err(EFAULT);
342         }
343         let mut out: MaybeUninit<T> = MaybeUninit::uninit();
344         // SAFETY: The local variable `out` is valid for writing `size_of::<T>()` bytes.
345         //
346         // By using the _copy_from_user variant, we skip the check_object_size check that verifies
347         // the kernel pointer. This mirrors the logic on the C side that skips the check when the
348         // length is a compile-time constant.
349         let res = unsafe {
350             bindings::_copy_from_user(
351                 out.as_mut_ptr().cast::<c_void>(),
352                 self.ptr.as_const_ptr(),
353                 len,
354             )
355         };
356         if res != 0 {
357             return Err(EFAULT);
358         }
359         self.ptr = self.ptr.wrapping_byte_add(len);
360         self.length -= len;
361         // SAFETY: The read above has initialized all bytes in `out`, and since `T` implements
362         // `FromBytes`, any bit-pattern is a valid value for this type.
363         Ok(unsafe { out.assume_init() })
364     }
365 
366     /// Reads the entirety of the user slice, appending it to the end of the provided buffer.
367     ///
368     /// Fails with [`EFAULT`] if the read happens on a bad address.
369     pub fn read_all<A: Allocator>(mut self, buf: &mut Vec<u8, A>, flags: Flags) -> Result {
370         let len = self.length;
371         buf.reserve(len, flags)?;
372 
373         // The call to `reserve` was successful, so the spare capacity is at least `len` bytes long.
374         self.read_raw(&mut buf.spare_capacity_mut()[..len])?;
375 
376         // SAFETY: Since the call to `read_raw` was successful, so the next `len` bytes of the
377         // vector have been initialized.
378         unsafe { buf.inc_len(len) };
379         Ok(())
380     }
381 
382     /// Read a NUL-terminated string from userspace and return it.
383     ///
384     /// The string is read into `buf` and a NUL-terminator is added if the end of `buf` is reached.
385     /// Since there must be space to add a NUL-terminator, the buffer must not be empty. The
386     /// returned `&CStr` points into `buf`.
387     ///
388     /// Fails with [`EFAULT`] if the read happens on a bad address (some data may have been
389     /// copied).
390     #[doc(alias = "strncpy_from_user")]
391     pub fn strcpy_into_buf<'buf>(self, buf: &'buf mut [u8]) -> Result<&'buf CStr> {
392         if buf.is_empty() {
393             return Err(EINVAL);
394         }
395 
396         // SAFETY: The types are compatible and `strncpy_from_user` doesn't write uninitialized
397         // bytes to `buf`.
398         let mut dst = unsafe { &mut *(core::ptr::from_mut(buf) as *mut [MaybeUninit<u8>]) };
399 
400         // We never read more than `self.length` bytes.
401         if dst.len() > self.length {
402             dst = &mut dst[..self.length];
403         }
404 
405         let mut len = raw_strncpy_from_user(dst, self.ptr)?;
406         if len < dst.len() {
407             // Add one to include the NUL-terminator.
408             len += 1;
409         } else if len < buf.len() {
410             // This implies that `len == dst.len() < buf.len()`.
411             //
412             // This means that we could not fill the entire buffer, but we had to stop reading
413             // because we hit the `self.length` limit of this `UserSliceReader`. Since we did not
414             // fill the buffer, we treat this case as if we tried to read past the `self.length`
415             // limit and received a page fault, which is consistent with other `UserSliceReader`
416             // methods that also return page faults when you exceed `self.length`.
417             return Err(EFAULT);
418         } else {
419             // This implies that `len == buf.len()`.
420             //
421             // This means that we filled the buffer exactly. In this case, we add a NUL-terminator
422             // and return it. Unlike the `len < dst.len()` branch, don't modify `len` because it
423             // already represents the length including the NUL-terminator.
424             //
425             // SAFETY: Due to the check at the beginning, the buffer is not empty.
426             unsafe { *buf.last_mut().unwrap_unchecked() = 0 };
427         }
428 
429         // This method consumes `self`, so it can only be called once, thus we do not need to
430         // update `self.length`. This sidesteps concerns such as whether `self.length` should be
431         // incremented by `len` or `len-1` in the `len == buf.len()` case.
432 
433         // SAFETY: There are two cases:
434         // * If we hit the `len < dst.len()` case, then `raw_strncpy_from_user` guarantees that
435         //   this slice contains exactly one NUL byte at the end of the string.
436         // * Otherwise, `raw_strncpy_from_user` guarantees that the string contained no NUL bytes,
437         //   and we have since added a NUL byte at the end.
438         Ok(unsafe { CStr::from_bytes_with_nul_unchecked(&buf[..len]) })
439     }
440 }
441 
442 /// A writer for [`UserSlice`].
443 ///
444 /// Used to incrementally write into the user slice.
445 pub struct UserSliceWriter {
446     ptr: UserPtr,
447     length: usize,
448 }
449 
450 impl UserSliceWriter {
451     /// Returns the amount of space remaining in this buffer.
452     ///
453     /// Note that even writing less than this number of bytes may fail.
454     pub fn len(&self) -> usize {
455         self.length
456     }
457 
458     /// Returns `true` if no more data can be written to this buffer.
459     pub fn is_empty(&self) -> bool {
460         self.length == 0
461     }
462 
463     /// Low-level write from a raw pointer.
464     ///
465     /// # Safety
466     ///
467     /// The caller must ensure that `from` is valid for reads of `len` bytes.
468     unsafe fn write_raw(&mut self, from: *const u8, len: usize) -> Result {
469         if len > self.length {
470             return Err(EFAULT);
471         }
472 
473         // SAFETY: Caller guarantees `from` is valid for `len` bytes (see this function's
474         // safety contract).
475         let res = unsafe { bindings::copy_to_user(self.ptr.as_mut_ptr(), from.cast(), len) };
476         if res != 0 {
477             return Err(EFAULT);
478         }
479         self.ptr = self.ptr.wrapping_byte_add(len);
480         self.length -= len;
481         Ok(())
482     }
483 
484     /// Writes raw data to this user pointer from a kernel buffer.
485     ///
486     /// Fails with [`EFAULT`] if the write happens on a bad address, or if the write goes out of
487     /// bounds of this [`UserSliceWriter`]. This call may modify the associated userspace slice even
488     /// if it returns an error.
489     pub fn write_slice(&mut self, data: &[u8]) -> Result {
490         // SAFETY: `data` is a valid slice, so `data.as_ptr()` is valid for
491         // reading `data.len()` bytes.
492         unsafe { self.write_raw(data.as_ptr(), data.len()) }
493     }
494 
495     /// Writes raw data to this user pointer from a DMA coherent allocation.
496     ///
497     /// Copies `count` bytes from `alloc` starting from `offset` into this userspace slice.
498     ///
499     /// # Errors
500     ///
501     /// - [`EOVERFLOW`]: `offset + count` overflows.
502     /// - [`ERANGE`]: `offset + count` exceeds the size of `alloc`, or `count` exceeds the
503     ///   size of the user-space buffer.
504     /// - [`EFAULT`]: the write hits a bad address or goes out of bounds of this
505     ///   [`UserSliceWriter`].
506     ///
507     /// This call may modify the associated userspace slice even if it returns an error.
508     ///
509     /// Note: The memory may be concurrently modified by hardware (e.g., DMA). In such cases,
510     /// the copied data may be inconsistent, but this does not cause undefined behavior.
511     ///
512     /// # Example
513     ///
514     /// Copy the first 256 bytes of a DMA coherent allocation into a userspace buffer:
515     ///
516     /// ```no_run
517     /// use kernel::uaccess::UserSliceWriter;
518     /// use kernel::dma::Coherent;
519     ///
520     /// fn copy_dma_to_user(
521     ///     mut writer: UserSliceWriter,
522     ///     alloc: &Coherent<[u8]>,
523     /// ) -> Result {
524     ///     writer.write_dma(alloc, 0, 256)
525     /// }
526     /// ```
527     pub fn write_dma(&mut self, alloc: &Coherent<[u8]>, offset: usize, count: usize) -> Result {
528         let len = alloc.size();
529         if offset.checked_add(count).ok_or(EOVERFLOW)? > len {
530             return Err(ERANGE);
531         }
532 
533         if count > self.len() {
534             return Err(ERANGE);
535         }
536 
537         // SAFETY: `as_ptr()` returns a valid pointer to a memory region of `count()` bytes, as
538         // guaranteed by the `Coherent` invariants. The check above ensures `offset + count <= len`.
539         let src_ptr = unsafe { alloc.as_ptr().cast::<u8>().add(offset) };
540 
541         // Note: Use `write_raw` instead of `write_slice` because the allocation is coherent
542         // memory that hardware may modify (e.g., DMA); we cannot form a `&[u8]` slice over
543         // such volatile memory.
544         //
545         // SAFETY: `src_ptr` points into the allocation and is valid for `count` bytes (see above).
546         unsafe { self.write_raw(src_ptr, count) }
547     }
548 
549     /// Writes raw data to this user pointer from a kernel buffer partially.
550     ///
551     /// This is the same as [`Self::write_slice`] but considers the given `offset` into `data` and
552     /// truncates the write to the boundaries of `self` and `data`.
553     ///
554     /// On success, returns the number of bytes written.
555     pub fn write_slice_partial(&mut self, data: &[u8], offset: usize) -> Result<usize> {
556         let end = offset.saturating_add(self.len()).min(data.len());
557 
558         let Some(src) = data.get(offset..end) else {
559             return Ok(0);
560         };
561 
562         self.write_slice(src)?;
563         Ok(src.len())
564     }
565 
566     /// Writes raw data to this user pointer from a kernel buffer partially.
567     ///
568     /// This is the same as [`Self::write_slice_partial`] but updates the given [`file::Offset`] by
569     /// the number of bytes written.
570     ///
571     /// This is equivalent to C's `simple_read_from_buffer()`.
572     ///
573     /// On success, returns the number of bytes written.
574     pub fn write_slice_file(&mut self, data: &[u8], offset: &mut file::Offset) -> Result<usize> {
575         if offset.is_negative() {
576             return Err(EINVAL);
577         }
578 
579         let Ok(offset_index) = (*offset).try_into() else {
580             return Ok(0);
581         };
582 
583         let written = self.write_slice_partial(data, offset_index)?;
584 
585         // OVERFLOW: `offset + written <= data.len() <= isize::MAX <= Offset::MAX`
586         *offset += written as i64;
587 
588         Ok(written)
589     }
590 
591     /// Writes the provided Rust value to this userspace pointer.
592     ///
593     /// Fails with [`EFAULT`] if the write happens on a bad address, or if the write goes out of
594     /// bounds of this [`UserSliceWriter`]. This call may modify the associated userspace slice even
595     /// if it returns an error.
596     pub fn write<T: AsBytes>(&mut self, value: &T) -> Result {
597         let len = size_of::<T>();
598         if len > self.length {
599             return Err(EFAULT);
600         }
601         // SAFETY: The reference points to a value of type `T`, so it is valid for reading
602         // `size_of::<T>()` bytes.
603         //
604         // By using the _copy_to_user variant, we skip the check_object_size check that verifies the
605         // kernel pointer. This mirrors the logic on the C side that skips the check when the length
606         // is a compile-time constant.
607         let res = unsafe {
608             bindings::_copy_to_user(
609                 self.ptr.as_mut_ptr(),
610                 core::ptr::from_ref(value).cast::<c_void>(),
611                 len,
612             )
613         };
614         if res != 0 {
615             return Err(EFAULT);
616         }
617         self.ptr = self.ptr.wrapping_byte_add(len);
618         self.length -= len;
619         Ok(())
620     }
621 }
622 
623 /// Reads a nul-terminated string into `dst` and returns the length.
624 ///
625 /// This reads from userspace until a NUL byte is encountered, or until `dst.len()` bytes have been
626 /// read. Fails with [`EFAULT`] if a read happens on a bad address (some data may have been
627 /// copied). When the end of the buffer is encountered, no NUL byte is added, so the string is
628 /// *not* guaranteed to be NUL-terminated when `Ok(dst.len())` is returned.
629 ///
630 /// # Guarantees
631 ///
632 /// When this function returns `Ok(len)`, it is guaranteed that the first `len` bytes of `dst` are
633 /// initialized and non-zero. Furthermore, if `len < dst.len()`, then `dst[len]` is a NUL byte.
634 #[inline]
635 fn raw_strncpy_from_user(dst: &mut [MaybeUninit<u8>], src: UserPtr) -> Result<usize> {
636     // CAST: Slice lengths are guaranteed to be `<= isize::MAX`.
637     let len = dst.len() as isize;
638 
639     // SAFETY: `dst` is valid for writing `dst.len()` bytes.
640     let res = unsafe {
641         bindings::strncpy_from_user(
642             dst.as_mut_ptr().cast::<c_char>(),
643             src.as_const_ptr().cast::<c_char>(),
644             len,
645         )
646     };
647 
648     if res < 0 {
649         return Err(Error::from_errno(res as i32));
650     }
651 
652     #[cfg(CONFIG_RUST_OVERFLOW_CHECKS)]
653     assert!(res <= len);
654 
655     // GUARANTEES: `strncpy_from_user` was successful, so `dst` has contents in accordance with the
656     // guarantees of this function.
657     Ok(res as usize)
658 }
659