kernel/
processbuffer.rs

1// Licensed under the Apache License, Version 2.0 or the MIT License.
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3// Copyright Tock Contributors 2022.
4
5//! Data structures for passing application memory to the kernel.
6//!
7//! A Tock process can pass read-write or read-only buffers into the
8//! kernel for it to use. The kernel checks that read-write buffers
9//! exist within a process's RAM address space, and that read-only
10//! buffers exist either within its RAM or flash address space. These
11//! buffers are shared with the allow_read_write() and
12//! allow_read_only() system calls.
13//!
14//! A read-write and read-only call is mapped to the high-level Rust
15//! types [`ReadWriteProcessBuffer`] and [`ReadOnlyProcessBuffer`]
16//! respectively. The memory regions can be accessed through the
17//! [`ReadableProcessBuffer`] and [`WriteableProcessBuffer`] traits,
18//! implemented on the process buffer structs.
19//!
20//! Each access to the buffer structs requires a liveness check to ensure that
21//! the process memory is still valid. For a more traditional interface, users
22//! can convert buffers into [`ReadableProcessSlice`] or
23//! [`WriteableProcessSlice`] and use these for the lifetime of their
24//! operations. Users cannot hold live-lived references to these slices,
25//! however.
26
27use core::cell::Cell;
28use core::marker::PhantomData;
29use core::ops::{Deref, Index, Range, RangeFrom, RangeTo};
30
31use crate::capabilities;
32use crate::process::{self, ProcessId};
33use crate::ErrorCode;
34
35/// Convert a process buffer's internal representation to a
36/// [`ReadableProcessSlice`].
37///
38/// This function will automatically convert zero-length process
39/// buffers into valid zero-sized Rust slices regardless of the value
40/// of `ptr`.
41///
42/// # Safety requirements
43///
44/// In the case of `len != 0`, the memory `[ptr; ptr + len)` must be
45/// within a single process' address space, and `ptr` must be
46/// nonzero. This memory region must be mapped as _readable_, and
47/// optionally _writable_ and _executable_. It must be allocated
48/// within a single process' address space for the entire lifetime
49/// `'a`.
50///
51/// It is sound for multiple overlapping [`ReadableProcessSlice`]s or
52/// [`WriteableProcessSlice`]s to be in scope at the same time.
53unsafe fn raw_processbuf_to_roprocessslice<'a>(
54    ptr: *const u8,
55    len: usize,
56) -> &'a ReadableProcessSlice {
57    // Transmute a reference to a slice of Cell<u8>s into a reference
58    // to a ReadableProcessSlice. This is possible as
59    // ReadableProcessSlice is a #[repr(transparent)] wrapper around a
60    // [ReadableProcessByte], which is a #[repr(transparent)] wrapper
61    // around a [Cell<u8>], which is a #[repr(transparent)] wrapper
62    // around an [UnsafeCell<u8>], which finally #[repr(transparent)]
63    // wraps a [u8]
64    core::mem::transmute::<&[u8], &ReadableProcessSlice>(
65        // Rust has very strict requirements on pointer validity[1]
66        // which also in part apply to accesses of length 0. We allow
67        // an application to supply arbitrary pointers if the buffer
68        // length is 0, but this is not allowed for Rust slices. For
69        // instance, a null pointer is _never_ valid, not even for
70        // accesses of size zero.
71        //
72        // To get a pointer which does not point to valid (allocated)
73        // memory, but is safe to construct for accesses of size zero,
74        // we must call NonNull::dangling(). The resulting pointer is
75        // guaranteed to be well-aligned and uphold the guarantees
76        // required for accesses of size zero.
77        //
78        // [1]: https://doc.rust-lang.org/core/ptr/index.html#safety
79        match len {
80            0 => core::slice::from_raw_parts(core::ptr::NonNull::<u8>::dangling().as_ptr(), 0),
81            _ => core::slice::from_raw_parts(ptr, len),
82        },
83    )
84}
85
86/// Convert an process buffers's internal representation to a
87/// [`WriteableProcessSlice`].
88///
89/// This function will automatically convert zero-length process
90/// buffers into valid zero-sized Rust slices regardless of the value
91/// of `ptr`.
92///
93/// # Safety requirements
94///
95/// In the case of `len != 0`, the memory `[ptr; ptr + len)` must be
96/// within a single process' address space, and `ptr` must be
97/// nonzero. This memory region must be mapped as _readable_ and
98/// _writable_, and optionally _executable_. It must be allocated
99/// within a single process' address space for the entire lifetime
100/// `'a`.
101///
102/// No other mutable or immutable Rust reference pointing to an
103/// overlapping memory region, which is not also created over
104/// `UnsafeCell`, may exist over the entire lifetime `'a`. Even though
105/// this effectively returns a slice of [`Cell`]s, writing to some
106/// memory through a [`Cell`] while another reference is in scope is
107/// unsound. Because a process is free to modify its memory, this is
108/// -- in a broader sense -- true for all process memory.
109///
110/// However, it is sound for multiple overlapping
111/// [`ReadableProcessSlice`]s or [`WriteableProcessSlice`]s to be in
112/// scope at the same time.
113unsafe fn raw_processbuf_to_rwprocessslice<'a>(
114    ptr: *mut u8,
115    len: usize,
116) -> &'a WriteableProcessSlice {
117    // Transmute a reference to a slice of Cell<u8>s into a reference
118    // to a ReadableProcessSlice. This is possible as
119    // ReadableProcessSlice is a #[repr(transparent)] wrapper around a
120    // [ReadableProcessByte], which is a #[repr(transparent)] wrapper
121    // around a [Cell<u8>], which is a #[repr(transparent)] wrapper
122    // around an [UnsafeCell<u8>], which finally #[repr(transparent)]
123    // wraps a [u8]
124    core::mem::transmute::<&[u8], &WriteableProcessSlice>(
125        // Rust has very strict requirements on pointer validity[1]
126        // which also in part apply to accesses of length 0. We allow
127        // an application to supply arbitrary pointers if the buffer
128        // length is 0, but this is not allowed for Rust slices. For
129        // instance, a null pointer is _never_ valid, not even for
130        // accesses of size zero.
131        //
132        // To get a pointer which does not point to valid (allocated)
133        // memory, but is safe to construct for accesses of size zero,
134        // we must call NonNull::dangling(). The resulting pointer is
135        // guaranteed to be well-aligned and uphold the guarantees
136        // required for accesses of size zero.
137        //
138        // [1]: https://doc.rust-lang.org/core/ptr/index.html#safety
139        match len {
140            0 => core::slice::from_raw_parts_mut(core::ptr::NonNull::<u8>::dangling().as_ptr(), 0),
141            _ => core::slice::from_raw_parts_mut(ptr, len),
142        },
143    )
144}
145
146/// A readable region of userspace process memory.
147///
148/// This trait can be used to gain read-only access to memory regions
149/// wrapped in either a [`ReadOnlyProcessBuffer`] or a
150/// [`ReadWriteProcessBuffer`] type.
151pub trait ReadableProcessBuffer {
152    /// Length of the memory region.
153    ///
154    /// If the process is no longer alive and the memory has been
155    /// reclaimed, this method must return 0.
156    ///
157    /// # Default Process Buffer
158    ///
159    /// A default instance of a process buffer must return 0.
160    fn len(&self) -> usize;
161
162    /// Pointer to the first byte of the userspace memory region.
163    ///
164    /// If the length of the initially shared memory region
165    /// (irrespective of the return value of
166    /// [`len`](ReadableProcessBuffer::len)) is 0, this function returns
167    /// a pointer to address `0x0`. This is because processes may
168    /// allow buffers with length 0 to share no memory with the
169    /// kernel. Because these buffers have zero length, they may have
170    /// any pointer value. However, these _dummy addresses_ should not
171    /// be leaked, so this method returns 0 for zero-length slices.
172    ///
173    /// # Default Process Buffer
174    ///
175    /// A default instance of a process buffer must return a pointer
176    /// to address `0x0`.
177    fn ptr(&self) -> *const u8;
178
179    /// Applies a function to the (read only) process slice reference
180    /// pointed to by the process buffer.
181    ///
182    /// If the process is no longer alive and the memory has been
183    /// reclaimed, this method must return
184    /// `Err(process::Error::NoSuchApp)`.
185    ///
186    /// # Default Process Buffer
187    ///
188    /// A default instance of a process buffer must return
189    /// `Err(process::Error::NoSuchApp)` without executing the passed
190    /// closure.
191    fn enter<F, R>(&self, fun: F) -> Result<R, process::Error>
192    where
193        F: FnOnce(&ReadableProcessSlice) -> R;
194}
195
196/// A readable and writeable region of userspace process memory.
197///
198/// This trait can be used to gain read-write access to memory regions
199/// wrapped in a [`ReadWriteProcessBuffer`].
200///
201/// This is a supertrait of [`ReadableProcessBuffer`], which features
202/// methods allowing mutable access.
203pub trait WriteableProcessBuffer: ReadableProcessBuffer {
204    /// Applies a function to the mutable process slice reference
205    /// pointed to by the [`ReadWriteProcessBuffer`].
206    ///
207    /// If the process is no longer alive and the memory has been
208    /// reclaimed, this method must return
209    /// `Err(process::Error::NoSuchApp)`.
210    ///
211    /// # Default Process Buffer
212    ///
213    /// A default instance of a process buffer must return
214    /// `Err(process::Error::NoSuchApp)` without executing the passed
215    /// closure.
216    fn mut_enter<F, R>(&self, fun: F) -> Result<R, process::Error>
217    where
218        F: FnOnce(&WriteableProcessSlice) -> R;
219}
220
221/// Read-only buffer shared by a userspace process.
222///
223/// This struct is provided to capsules when a process `allow`s a
224/// particular section of its memory to the kernel and gives the
225/// kernel read access to this memory.
226///
227/// It can be used to obtain a [`ReadableProcessSlice`], which is
228/// based around a slice of [`Cell`]s. This is because a userspace can
229/// `allow` overlapping sections of memory into different
230/// [`ReadableProcessSlice`]. Having at least one mutable Rust slice
231/// along with read-only slices to overlapping memory in Rust violates
232/// Rust's aliasing rules. A slice of [`Cell`]s avoids this issue by
233/// explicitly supporting interior mutability. Still, a memory barrier
234/// prior to switching to userspace is required, as the compiler is
235/// free to reorder reads and writes, even through [`Cell`]s.
236pub struct ReadOnlyProcessBuffer {
237    ptr: *const u8,
238    len: usize,
239    process_id: Option<ProcessId>,
240}
241
242impl ReadOnlyProcessBuffer {
243    /// Construct a new [`ReadOnlyProcessBuffer`] over a given pointer and
244    /// length.
245    ///
246    /// # Safety requirements
247    ///
248    /// Refer to the safety requirements of
249    /// [`ReadOnlyProcessBuffer::new_external`].
250    pub(crate) unsafe fn new(ptr: *const u8, len: usize, process_id: ProcessId) -> Self {
251        ReadOnlyProcessBuffer {
252            ptr,
253            len,
254            process_id: Some(process_id),
255        }
256    }
257
258    /// Construct a new [`ReadOnlyProcessBuffer`] over a given pointer
259    /// and length.
260    ///
261    /// Publicly accessible constructor, which requires the
262    /// [`capabilities::ExternalProcessCapability`] capability. This
263    /// is provided to allow implementations of the
264    /// [`Process`](crate::process::Process) trait outside of the
265    /// `kernel` crate.
266    ///
267    /// # Safety requirements
268    ///
269    /// If the length is `0`, an arbitrary pointer may be passed into
270    /// `ptr`. It does not necessarily have to point to allocated
271    /// memory, nor does it have to meet [Rust's pointer validity
272    /// requirements](https://doc.rust-lang.org/core/ptr/index.html#safety).
273    /// [`ReadOnlyProcessBuffer`] must ensure that all Rust slices
274    /// with a length of `0` must be constructed over a valid (but not
275    /// necessarily allocated) base pointer.
276    ///
277    /// If the length is not `0`, the memory region of `[ptr; ptr +
278    /// len)` must be valid memory of the process of the given
279    /// [`ProcessId`]. It must be allocated and and accessible over
280    /// the entire lifetime of the [`ReadOnlyProcessBuffer`]. It must
281    /// not point to memory outside of the process' accessible memory
282    /// range, or point (in part) to other processes or kernel
283    /// memory. The `ptr` must meet [Rust's requirements for pointer
284    /// validity](https://doc.rust-lang.org/core/ptr/index.html#safety),
285    /// in particular it must have a minimum alignment of
286    /// `core::mem::align_of::<u8>()` on the respective platform. It
287    /// must point to memory mapped as _readable_ and optionally
288    /// _writable_ and _executable_.
289    pub unsafe fn new_external(
290        ptr: *const u8,
291        len: usize,
292        process_id: ProcessId,
293        _cap: &dyn capabilities::ExternalProcessCapability,
294    ) -> Self {
295        Self::new(ptr, len, process_id)
296    }
297
298    /// Consumes the ReadOnlyProcessBuffer, returning its constituent
299    /// pointer and size. This ensures that there cannot
300    /// simultaneously be both a `ReadOnlyProcessBuffer` and a pointer
301    /// to its internal data.
302    ///
303    /// `consume` can be used when the kernel needs to pass the
304    /// underlying values across the kernel-to-user boundary (e.g., in
305    /// return values to system calls).
306    pub(crate) fn consume(self) -> (*const u8, usize) {
307        (self.ptr, self.len)
308    }
309}
310
311impl ReadableProcessBuffer for ReadOnlyProcessBuffer {
312    /// Return the length of the buffer in bytes.
313    fn len(&self) -> usize {
314        self.process_id
315            .map_or(0, |pid| pid.kernel.process_map_or(0, pid, |_| self.len))
316    }
317
318    /// Return the pointer to the start of the buffer.
319    fn ptr(&self) -> *const u8 {
320        if self.len == 0 {
321            core::ptr::null::<u8>()
322        } else {
323            self.ptr
324        }
325    }
326
327    /// Access the contents of the buffer in a closure.
328    ///
329    /// This verifies the process is still valid before accessing the underlying
330    /// memory.
331    fn enter<F, R>(&self, fun: F) -> Result<R, process::Error>
332    where
333        F: FnOnce(&ReadableProcessSlice) -> R,
334    {
335        match self.process_id {
336            None => Err(process::Error::NoSuchApp),
337            Some(pid) => pid
338                .kernel
339                .process_map_or(Err(process::Error::NoSuchApp), pid, |_| {
340                    // Safety: `kernel.process_map_or()` validates that
341                    // the process still exists and its memory is still
342                    // valid. In particular, `Process` tracks the "high water
343                    // mark" of memory that the process has `allow`ed to the
344                    // kernel. Because `Process` does not feature an API to
345                    // move the "high water mark" down again, which would be
346                    // called once a `ProcessBuffer` has been passed back into
347                    // the kernel, a given `Process` implementation must assume
348                    // that the memory described by a once-allowed
349                    // `ProcessBuffer` is still in use, and thus will not
350                    // permit the process to free any memory after it has
351                    // been `allow`ed to the kernel once. This guarantees
352                    // that the buffer is safe to convert into a slice
353                    // here. For more information, refer to the
354                    // comment and subsequent discussion on tock/tock#2632:
355                    // https://github.com/tock/tock/pull/2632#issuecomment-869974365
356                    Ok(fun(unsafe {
357                        raw_processbuf_to_roprocessslice(self.ptr, self.len)
358                    }))
359                }),
360        }
361    }
362}
363
364impl Default for ReadOnlyProcessBuffer {
365    fn default() -> Self {
366        ReadOnlyProcessBuffer {
367            ptr: core::ptr::null_mut::<u8>(),
368            len: 0,
369            process_id: None,
370        }
371    }
372}
373
374/// Provides access to a [`ReadOnlyProcessBuffer`] with a restricted lifetime.
375/// This automatically dereferences into a ReadOnlyProcessBuffer
376pub struct ReadOnlyProcessBufferRef<'a> {
377    buf: ReadOnlyProcessBuffer,
378    _phantom: PhantomData<&'a ()>,
379}
380
381impl ReadOnlyProcessBufferRef<'_> {
382    /// Construct a new [`ReadOnlyProcessBufferRef`] over a given pointer and
383    /// length with a lifetime derived from the caller.
384    ///
385    /// # Safety requirements
386    ///
387    /// Refer to the safety requirements of
388    /// [`ReadOnlyProcessBuffer::new_external`]. The derived lifetime can
389    /// help enforce the invariant that this incoming pointer may only
390    /// be access for a certain duration.
391    pub(crate) unsafe fn new(ptr: *const u8, len: usize, process_id: ProcessId) -> Self {
392        Self {
393            buf: ReadOnlyProcessBuffer::new(ptr, len, process_id),
394            _phantom: PhantomData,
395        }
396    }
397}
398
399impl Deref for ReadOnlyProcessBufferRef<'_> {
400    type Target = ReadOnlyProcessBuffer;
401    fn deref(&self) -> &Self::Target {
402        &self.buf
403    }
404}
405
406/// Read-writable buffer shared by a userspace process.
407///
408/// This struct is provided to capsules when a process `allows` a
409/// particular section of its memory to the kernel and gives the
410/// kernel read and write access to this memory.
411///
412/// It can be used to obtain a [`WriteableProcessSlice`], which is
413/// based around a slice of [`Cell`]s. This is because a userspace can
414/// `allow` overlapping sections of memory into different
415/// [`WriteableProcessSlice`]. Having at least one mutable Rust slice
416/// along with read-only or other mutable slices to overlapping memory
417/// in Rust violates Rust's aliasing rules. A slice of [`Cell`]s
418/// avoids this issue by explicitly supporting interior
419/// mutability. Still, a memory barrier prior to switching to
420/// userspace is required, as the compiler is free to reorder reads
421/// and writes, even through [`Cell`]s.
422pub struct ReadWriteProcessBuffer {
423    ptr: *mut u8,
424    len: usize,
425    process_id: Option<ProcessId>,
426}
427
428impl ReadWriteProcessBuffer {
429    /// Construct a new [`ReadWriteProcessBuffer`] over a given
430    /// pointer and length.
431    ///
432    /// # Safety requirements
433    ///
434    /// Refer to the safety requirements of
435    /// [`ReadWriteProcessBuffer::new_external`].
436    pub(crate) unsafe fn new(ptr: *mut u8, len: usize, process_id: ProcessId) -> Self {
437        ReadWriteProcessBuffer {
438            ptr,
439            len,
440            process_id: Some(process_id),
441        }
442    }
443
444    /// Construct a new [`ReadWriteProcessBuffer`] over a given
445    /// pointer and length.
446    ///
447    /// Publicly accessible constructor, which requires the
448    /// [`capabilities::ExternalProcessCapability`] capability. This
449    /// is provided to allow implementations of the
450    /// [`Process`](crate::process::Process) trait outside of the
451    /// `kernel` crate.
452    ///
453    /// # Safety requirements
454    ///
455    /// If the length is `0`, an arbitrary pointer may be passed into
456    /// `ptr`. It does not necessarily have to point to allocated
457    /// memory, nor does it have to meet [Rust's pointer validity
458    /// requirements](https://doc.rust-lang.org/core/ptr/index.html#safety).
459    /// [`ReadWriteProcessBuffer`] must ensure that all Rust slices
460    /// with a length of `0` must be constructed over a valid (but not
461    /// necessarily allocated) base pointer.
462    ///
463    /// If the length is not `0`, the memory region of `[ptr; ptr +
464    /// len)` must be valid memory of the process of the given
465    /// [`ProcessId`]. It must be allocated and and accessible over
466    /// the entire lifetime of the [`ReadWriteProcessBuffer`]. It must
467    /// not point to memory outside of the process' accessible memory
468    /// range, or point (in part) to other processes or kernel
469    /// memory. The `ptr` must meet [Rust's requirements for pointer
470    /// validity](https://doc.rust-lang.org/core/ptr/index.html#safety),
471    /// in particular it must have a minimum alignment of
472    /// `core::mem::align_of::<u8>()` on the respective platform. It
473    /// must point to memory mapped as _readable_ and optionally
474    /// _writable_ and _executable_.
475    pub unsafe fn new_external(
476        ptr: *mut u8,
477        len: usize,
478        process_id: ProcessId,
479        _cap: &dyn capabilities::ExternalProcessCapability,
480    ) -> Self {
481        Self::new(ptr, len, process_id)
482    }
483
484    /// Consumes the ReadWriteProcessBuffer, returning its constituent
485    /// pointer and size. This ensures that there cannot
486    /// simultaneously be both a `ReadWriteProcessBuffer` and a pointer to
487    /// its internal data.
488    ///
489    /// `consume` can be used when the kernel needs to pass the
490    /// underlying values across the kernel-to-user boundary (e.g., in
491    /// return values to system calls).
492    pub(crate) fn consume(self) -> (*mut u8, usize) {
493        (self.ptr, self.len)
494    }
495
496    /// This is a `const` version of `Default::default` with the same
497    /// semantics.
498    ///
499    /// Having a const initializer allows initializing a fixed-size
500    /// array with default values without the struct being marked
501    /// `Copy` as such:
502    ///
503    /// ```
504    /// use kernel::processbuffer::ReadWriteProcessBuffer;
505    /// const DEFAULT_RWPROCBUF_VAL: ReadWriteProcessBuffer
506    ///     = ReadWriteProcessBuffer::const_default();
507    /// let my_array = [DEFAULT_RWPROCBUF_VAL; 12];
508    /// ```
509    pub const fn const_default() -> Self {
510        Self {
511            ptr: 0x0 as *mut u8,
512            len: 0,
513            process_id: None,
514        }
515    }
516}
517
518impl ReadableProcessBuffer for ReadWriteProcessBuffer {
519    /// Return the length of the buffer in bytes.
520    fn len(&self) -> usize {
521        self.process_id
522            .map_or(0, |pid| pid.kernel.process_map_or(0, pid, |_| self.len))
523    }
524
525    /// Return the pointer to the start of the buffer.
526    fn ptr(&self) -> *const u8 {
527        if self.len == 0 {
528            core::ptr::null::<u8>()
529        } else {
530            self.ptr
531        }
532    }
533
534    /// Access the contents of the buffer in a closure.
535    ///
536    /// This verifies the process is still valid before accessing the underlying
537    /// memory.
538    fn enter<F, R>(&self, fun: F) -> Result<R, process::Error>
539    where
540        F: FnOnce(&ReadableProcessSlice) -> R,
541    {
542        match self.process_id {
543            None => Err(process::Error::NoSuchApp),
544            Some(pid) => pid
545                .kernel
546                .process_map_or(Err(process::Error::NoSuchApp), pid, |_| {
547                    // Safety: `kernel.process_map_or()` validates that
548                    // the process still exists and its memory is still
549                    // valid. In particular, `Process` tracks the "high water
550                    // mark" of memory that the process has `allow`ed to the
551                    // kernel. Because `Process` does not feature an API to
552                    // move the "high water mark" down again, which would be
553                    // called once a `ProcessBuffer` has been passed back into
554                    // the kernel, a given `Process` implementation must assume
555                    // that the memory described by a once-allowed
556                    // `ProcessBuffer` is still in use, and thus will not
557                    // permit the process to free any memory after it has
558                    // been `allow`ed to the kernel once. This guarantees
559                    // that the buffer is safe to convert into a slice
560                    // here. For more information, refer to the
561                    // comment and subsequent discussion on tock/tock#2632:
562                    // https://github.com/tock/tock/pull/2632#issuecomment-869974365
563                    Ok(fun(unsafe {
564                        raw_processbuf_to_roprocessslice(self.ptr, self.len)
565                    }))
566                }),
567        }
568    }
569}
570
571impl WriteableProcessBuffer for ReadWriteProcessBuffer {
572    fn mut_enter<F, R>(&self, fun: F) -> Result<R, process::Error>
573    where
574        F: FnOnce(&WriteableProcessSlice) -> R,
575    {
576        match self.process_id {
577            None => Err(process::Error::NoSuchApp),
578            Some(pid) => pid
579                .kernel
580                .process_map_or(Err(process::Error::NoSuchApp), pid, |_| {
581                    // Safety: `kernel.process_map_or()` validates that
582                    // the process still exists and its memory is still
583                    // valid. In particular, `Process` tracks the "high water
584                    // mark" of memory that the process has `allow`ed to the
585                    // kernel. Because `Process` does not feature an API to
586                    // move the "high water mark" down again, which would be
587                    // called once a `ProcessBuffer` has been passed back into
588                    // the kernel, a given `Process` implementation must assume
589                    // that the memory described by a once-allowed
590                    // `ProcessBuffer` is still in use, and thus will not
591                    // permit the process to free any memory after it has
592                    // been `allow`ed to the kernel once. This guarantees
593                    // that the buffer is safe to convert into a slice
594                    // here. For more information, refer to the
595                    // comment and subsequent discussion on tock/tock#2632:
596                    // https://github.com/tock/tock/pull/2632#issuecomment-869974365
597                    Ok(fun(unsafe {
598                        raw_processbuf_to_rwprocessslice(self.ptr, self.len)
599                    }))
600                }),
601        }
602    }
603}
604
605impl Default for ReadWriteProcessBuffer {
606    fn default() -> Self {
607        Self::const_default()
608    }
609}
610
611/// Provides access to a [`ReadWriteProcessBuffer`] with a restricted lifetime.
612/// This automatically dereferences into a ReadWriteProcessBuffer
613pub struct ReadWriteProcessBufferRef<'a> {
614    buf: ReadWriteProcessBuffer,
615    _phantom: PhantomData<&'a ()>,
616}
617
618impl ReadWriteProcessBufferRef<'_> {
619    /// Construct a new [`ReadWriteProcessBufferRef`] over a given pointer and
620    /// length with a lifetime derived from the caller.
621    ///
622    /// # Safety requirements
623    ///
624    /// Refer to the safety requirements of
625    /// [`ReadWriteProcessBuffer::new_external`]. The derived lifetime can
626    /// help enforce the invariant that this incoming pointer may only
627    /// be access for a certain duration.
628    pub(crate) unsafe fn new(ptr: *mut u8, len: usize, process_id: ProcessId) -> Self {
629        Self {
630            buf: ReadWriteProcessBuffer::new(ptr, len, process_id),
631            _phantom: PhantomData,
632        }
633    }
634}
635
636impl Deref for ReadWriteProcessBufferRef<'_> {
637    type Target = ReadWriteProcessBuffer;
638    fn deref(&self) -> &Self::Target {
639        &self.buf
640    }
641}
642
643/// A shareable region of userspace memory.
644///
645/// This trait can be used to gain read-write access to memory regions
646/// wrapped in a ProcessBuffer type.
647// We currently don't need any special functionality in the kernel for this
648// type so we alias it as `ReadWriteProcessBuffer`.
649pub type UserspaceReadableProcessBuffer = ReadWriteProcessBuffer;
650
651/// Equivalent of the Rust core library's
652/// [`SliceIndex`](core::slice::SliceIndex) type for process slices.
653///
654/// This helper trait is used to abstract over indexing operators into
655/// process slices, and is used to "overload" the `.get()` methods
656/// such that it can be called with multiple different indexing
657/// operators.
658///
659/// While we can use the core library's `SliceIndex` trait, parameterized over
660/// our own `ProcessSlice` types, this trait includes mandatory methods that are
661/// undesirable for the process buffer infrastructure, such as unchecked or
662/// mutable index operations. Furthermore, implementing it requires the
663/// `slice_index_methods` nightly feature. Thus we vendor our own, small variant
664/// of this trait.
665pub trait ProcessSliceIndex<PB: ?Sized>: private_process_slice_index::Sealed {
666    type Output: ?Sized;
667    fn get(self, slice: &PB) -> Option<&Self::Output>;
668    fn index(self, slice: &PB) -> &Self::Output;
669}
670
671// Analog to `private_slice_index` from
672// https://github.com/rust-lang/rust/blob/a1eceec00b2684f947481696ae2322e20d59db60/library/core/src/slice/index.rs#L149
673mod private_process_slice_index {
674    use core::ops::{Range, RangeFrom, RangeTo};
675
676    pub trait Sealed {}
677
678    impl Sealed for usize {}
679    impl Sealed for Range<usize> {}
680    impl Sealed for RangeFrom<usize> {}
681    impl Sealed for RangeTo<usize> {}
682}
683
684/// Read-only wrapper around a [`Cell`]
685///
686/// This type is used in providing the [`ReadableProcessSlice`]. The
687/// memory over which a [`ReadableProcessSlice`] exists must never be
688/// written to by the kernel. However, it may either exist in flash
689/// (read-only memory) or RAM (read-writeable memory). Consequently, a
690/// process may `allow` memory overlapping with a
691/// [`ReadOnlyProcessBuffer`] also simultaneously through a
692/// [`ReadWriteProcessBuffer`]. Hence, the kernel can have two
693/// references to the same memory, where one can lead to mutation of
694/// the memory contents. Therefore, the kernel must use [`Cell`]s
695/// around the bytes shared with userspace, to avoid violating Rust's
696/// aliasing rules.
697///
698/// This read-only wrapper around a [`Cell`] only exposes methods
699/// which are safe to call on a process-shared read-only `allow`
700/// memory.
701#[repr(transparent)]
702pub struct ReadableProcessByte {
703    cell: Cell<u8>,
704}
705
706impl ReadableProcessByte {
707    #[inline]
708    pub fn get(&self) -> u8 {
709        self.cell.get()
710    }
711}
712
713/// Readable and accessible slice of memory of a process buffer.
714///
715///
716/// The only way to obtain this struct is through a
717/// [`ReadWriteProcessBuffer`] or [`ReadOnlyProcessBuffer`].
718///
719/// Slices provide a more convenient, traditional interface to process
720/// memory. These slices are transient, as the underlying buffer must
721/// be checked each time a slice is created. This is usually enforced
722/// by the anonymous lifetime defined by the creation of the slice.
723#[repr(transparent)]
724pub struct ReadableProcessSlice {
725    slice: [ReadableProcessByte],
726}
727
728fn cast_byte_slice_to_process_slice(byte_slice: &[ReadableProcessByte]) -> &ReadableProcessSlice {
729    // As ReadableProcessSlice is a transparent wrapper around its inner type,
730    // [ReadableProcessByte], we can safely transmute a reference to the inner
731    // type as a reference to the outer type with the same lifetime.
732    unsafe { core::mem::transmute::<&[ReadableProcessByte], &ReadableProcessSlice>(byte_slice) }
733}
734
735// Allow a u8 slice to be viewed as a ReadableProcessSlice to allow client code
736// to be authored once and accept either [u8] or ReadableProcessSlice.
737impl<'a> From<&'a [u8]> for &'a ReadableProcessSlice {
738    fn from(val: &'a [u8]) -> Self {
739        // # Safety
740        //
741        // The layout of a [u8] and ReadableProcessSlice are guaranteed to be
742        // the same. This also extends the lifetime of the buffer, so aliasing
743        // rules are thus maintained properly.
744        unsafe { core::mem::transmute(val) }
745    }
746}
747
748// Allow a mutable u8 slice to be viewed as a ReadableProcessSlice to allow
749// client code to be authored once and accept either [u8] or
750// ReadableProcessSlice.
751impl<'a> From<&'a mut [u8]> for &'a ReadableProcessSlice {
752    fn from(val: &'a mut [u8]) -> Self {
753        // # Safety
754        //
755        // The layout of a [u8] and ReadableProcessSlice are guaranteed to be
756        // the same. This also extends the mutable lifetime of the buffer, so
757        // aliasing rules are thus maintained properly.
758        unsafe { core::mem::transmute(val) }
759    }
760}
761
762impl ReadableProcessSlice {
763    /// Copy the contents of a [`ReadableProcessSlice`] into a mutable
764    /// slice reference.
765    ///
766    /// The length of `self` must be the same as `dest`. Subslicing
767    /// can be used to obtain a slice of matching length.
768    ///
769    /// # Panics
770    ///
771    /// This function will panic if `self.len() != dest.len()`.
772    pub fn copy_to_slice(&self, dest: &mut [u8]) {
773        // The panic code path was put into a cold function to not
774        // bloat the call site.
775        #[inline(never)]
776        #[cold]
777        #[track_caller]
778        fn len_mismatch_fail(dst_len: usize, src_len: usize) -> ! {
779            panic!(
780                "source slice length ({}) does not match destination slice length ({})",
781                src_len, dst_len,
782            );
783        }
784
785        if self.copy_to_slice_or_err(dest).is_err() {
786            len_mismatch_fail(dest.len(), self.len());
787        }
788    }
789
790    /// Copy the contents of a [`ReadableProcessSlice`] into a mutable
791    /// slice reference.
792    ///
793    /// The length of `self` must be the same as `dest`. Subslicing
794    /// can be used to obtain a slice of matching length.
795    pub fn copy_to_slice_or_err(&self, dest: &mut [u8]) -> Result<(), ErrorCode> {
796        // Method implemetation adopted from the
797        // core::slice::copy_from_slice method implementation:
798        // https://doc.rust-lang.org/src/core/slice/mod.rs.html#3034-3036
799
800        if self.len() != dest.len() {
801            Err(ErrorCode::SIZE)
802        } else {
803            // _If_ this turns out to not be efficiently optimized, it
804            // should be possible to use a ptr::copy_nonoverlapping here
805            // given we have exclusive mutable access to the destination
806            // slice which will never be in process memory, and the layout
807            // of &[ReadableProcessByte] is guaranteed to be compatible to
808            // &[u8].
809            for (i, b) in self.slice.iter().enumerate() {
810                dest[i] = b.get();
811            }
812            Ok(())
813        }
814    }
815
816    /// Return the length of the slice in bytes.
817    pub fn len(&self) -> usize {
818        self.slice.len()
819    }
820
821    /// Return an iterator over the bytes of the slice.
822    pub fn iter(&self) -> core::slice::Iter<'_, ReadableProcessByte> {
823        self.slice.iter()
824    }
825
826    /// Iterate the slice in chunks.
827    pub fn chunks(
828        &self,
829        chunk_size: usize,
830    ) -> impl core::iter::Iterator<Item = &ReadableProcessSlice> {
831        self.slice
832            .chunks(chunk_size)
833            .map(cast_byte_slice_to_process_slice)
834    }
835
836    /// Access a portion of the slice with bounds checking. If the access is not
837    /// within the slice then `None` is returned.
838    pub fn get<I: ProcessSliceIndex<Self>>(
839        &self,
840        index: I,
841    ) -> Option<&<I as ProcessSliceIndex<Self>>::Output> {
842        index.get(self)
843    }
844
845    /// Access a portion of the slice with bounds checking. If the access is not
846    /// within the slice then `None` is returned.
847    #[deprecated = "Use ReadableProcessSlice::get instead"]
848    pub fn get_from(&self, range: RangeFrom<usize>) -> Option<&ReadableProcessSlice> {
849        range.get(self)
850    }
851
852    /// Access a portion of the slice with bounds checking. If the access is not
853    /// within the slice then `None` is returned.
854    #[deprecated = "Use ReadableProcessSlice::get instead"]
855    pub fn get_to(&self, range: RangeTo<usize>) -> Option<&ReadableProcessSlice> {
856        range.get(self)
857    }
858}
859
860impl ProcessSliceIndex<ReadableProcessSlice> for usize {
861    type Output = ReadableProcessByte;
862
863    fn get(self, slice: &ReadableProcessSlice) -> Option<&Self::Output> {
864        slice.slice.get(self)
865    }
866
867    fn index(self, slice: &ReadableProcessSlice) -> &Self::Output {
868        &slice.slice[self]
869    }
870}
871
872impl ProcessSliceIndex<ReadableProcessSlice> for Range<usize> {
873    type Output = ReadableProcessSlice;
874
875    fn get(self, slice: &ReadableProcessSlice) -> Option<&Self::Output> {
876        slice.slice.get(self).map(cast_byte_slice_to_process_slice)
877    }
878
879    fn index(self, slice: &ReadableProcessSlice) -> &Self::Output {
880        cast_byte_slice_to_process_slice(&slice.slice[self])
881    }
882}
883
884impl ProcessSliceIndex<ReadableProcessSlice> for RangeFrom<usize> {
885    type Output = ReadableProcessSlice;
886
887    fn get(self, slice: &ReadableProcessSlice) -> Option<&Self::Output> {
888        slice.slice.get(self).map(cast_byte_slice_to_process_slice)
889    }
890
891    fn index(self, slice: &ReadableProcessSlice) -> &Self::Output {
892        cast_byte_slice_to_process_slice(&slice.slice[self])
893    }
894}
895
896impl ProcessSliceIndex<ReadableProcessSlice> for RangeTo<usize> {
897    type Output = ReadableProcessSlice;
898
899    fn get(self, slice: &ReadableProcessSlice) -> Option<&Self::Output> {
900        slice.slice.get(self).map(cast_byte_slice_to_process_slice)
901    }
902
903    fn index(self, slice: &ReadableProcessSlice) -> &Self::Output {
904        cast_byte_slice_to_process_slice(&slice.slice[self])
905    }
906}
907
908impl<I: ProcessSliceIndex<Self>> Index<I> for ReadableProcessSlice {
909    type Output = I::Output;
910
911    fn index(&self, index: I) -> &Self::Output {
912        index.index(self)
913    }
914}
915
916/// Read-writeable and accessible slice of memory of a process buffer
917///
918/// The only way to obtain this struct is through a
919/// [`ReadWriteProcessBuffer`].
920///
921/// Slices provide a more convenient, traditional interface to process
922/// memory. These slices are transient, as the underlying buffer must
923/// be checked each time a slice is created. This is usually enforced
924/// by the anonymous lifetime defined by the creation of the slice.
925#[repr(transparent)]
926pub struct WriteableProcessSlice {
927    slice: [Cell<u8>],
928}
929
930fn cast_cell_slice_to_process_slice(cell_slice: &[Cell<u8>]) -> &WriteableProcessSlice {
931    // # Safety
932    //
933    // As WriteableProcessSlice is a transparent wrapper around its inner type,
934    // [Cell<u8>], we can safely transmute a reference to the inner type as the
935    // outer type with the same lifetime.
936    unsafe { core::mem::transmute(cell_slice) }
937}
938
939// Allow a mutable u8 slice to be viewed as a WritableProcessSlice to allow
940// client code to be authored once and accept either [u8] or
941// WriteableProcessSlice.
942impl<'a> From<&'a mut [u8]> for &'a WriteableProcessSlice {
943    fn from(val: &'a mut [u8]) -> Self {
944        // # Safety
945        //
946        // The layout of a [u8] and WriteableProcessSlice are guaranteed to be
947        // the same. This also extends the mutable lifetime of the buffer, so
948        // aliasing rules are thus maintained properly.
949        unsafe { core::mem::transmute(val) }
950    }
951}
952
953impl WriteableProcessSlice {
954    /// Copy the contents of a [`WriteableProcessSlice`] into a mutable
955    /// slice reference.
956    ///
957    /// The length of `self` must be the same as `dest`. Subslicing
958    /// can be used to obtain a slice of matching length.
959    ///
960    /// # Panics
961    ///
962    /// This function will panic if `self.len() != dest.len()`.
963    pub fn copy_to_slice(&self, dest: &mut [u8]) {
964        // The panic code path was put into a cold function to not
965        // bloat the call site.
966        #[inline(never)]
967        #[cold]
968        #[track_caller]
969        fn len_mismatch_fail(dst_len: usize, src_len: usize) -> ! {
970            panic!(
971                "source slice length ({}) does not match destination slice length ({})",
972                src_len, dst_len,
973            );
974        }
975
976        if self.copy_to_slice_or_err(dest).is_err() {
977            len_mismatch_fail(dest.len(), self.len());
978        }
979    }
980
981    /// Copy the contents of a [`WriteableProcessSlice`] into a mutable
982    /// slice reference.
983    ///
984    /// The length of `self` must be the same as `dest`. Subslicing
985    /// can be used to obtain a slice of matching length.
986    pub fn copy_to_slice_or_err(&self, dest: &mut [u8]) -> Result<(), ErrorCode> {
987        // Method implemetation adopted from the
988        // core::slice::copy_from_slice method implementation:
989        // https://doc.rust-lang.org/src/core/slice/mod.rs.html#3034-3036
990
991        if self.len() != dest.len() {
992            Err(ErrorCode::SIZE)
993        } else {
994            // _If_ this turns out to not be efficiently optimized, it
995            // should be possible to use a ptr::copy_nonoverlapping here
996            // given we have exclusive mutable access to the destination
997            // slice which will never be in process memory, and the layout
998            // of &[Cell<u8>] is guaranteed to be compatible to &[u8].
999            self.slice
1000                .iter()
1001                .zip(dest.iter_mut())
1002                .for_each(|(src, dst)| *dst = src.get());
1003            Ok(())
1004        }
1005    }
1006
1007    /// Copy the contents of a slice of bytes into a [`WriteableProcessSlice`].
1008    ///
1009    /// The length of `src` must be the same as `self`. Subslicing can
1010    /// be used to obtain a slice of matching length.
1011    ///
1012    /// # Panics
1013    ///
1014    /// This function will panic if `src.len() != self.len()`.
1015    pub fn copy_from_slice(&self, src: &[u8]) {
1016        // Method implemetation adopted from the
1017        // core::slice::copy_from_slice method implementation:
1018        // https://doc.rust-lang.org/src/core/slice/mod.rs.html#3034-3036
1019
1020        // The panic code path was put into a cold function to not
1021        // bloat the call site.
1022        #[inline(never)]
1023        #[cold]
1024        #[track_caller]
1025        fn len_mismatch_fail(dst_len: usize, src_len: usize) -> ! {
1026            panic!(
1027                "src slice len ({}) != dest slice len ({})",
1028                src_len, dst_len,
1029            );
1030        }
1031
1032        if self.copy_from_slice_or_err(src).is_err() {
1033            len_mismatch_fail(self.len(), src.len());
1034        }
1035    }
1036
1037    /// Copy the contents of a slice of bytes into a [`WriteableProcessSlice`].
1038    ///
1039    /// The length of `src` must be the same as `self`. Subslicing can
1040    /// be used to obtain a slice of matching length.
1041    pub fn copy_from_slice_or_err(&self, src: &[u8]) -> Result<(), ErrorCode> {
1042        // Method implemetation adopted from the
1043        // core::slice::copy_from_slice method implementation:
1044        // https://doc.rust-lang.org/src/core/slice/mod.rs.html#3034-3036
1045
1046        if self.len() != src.len() {
1047            Err(ErrorCode::SIZE)
1048        } else {
1049            // _If_ this turns out to not be efficiently optimized, it
1050            // should be possible to use a ptr::copy_nonoverlapping here
1051            // given we have exclusive mutable access to the destination
1052            // slice which will never be in process memory, and the layout
1053            // of &[Cell<u8>] is guaranteed to be compatible to &[u8].
1054            src.iter()
1055                .zip(self.slice.iter())
1056                .for_each(|(src, dst)| dst.set(*src));
1057            Ok(())
1058        }
1059    }
1060
1061    /// Return the length of the slice in bytes.
1062    pub fn len(&self) -> usize {
1063        self.slice.len()
1064    }
1065
1066    /// Return an iterator over the slice.
1067    pub fn iter(&self) -> core::slice::Iter<'_, Cell<u8>> {
1068        self.slice.iter()
1069    }
1070
1071    /// Iterate over the slice in chunks.
1072    pub fn chunks(
1073        &self,
1074        chunk_size: usize,
1075    ) -> impl core::iter::Iterator<Item = &WriteableProcessSlice> {
1076        self.slice
1077            .chunks(chunk_size)
1078            .map(cast_cell_slice_to_process_slice)
1079    }
1080
1081    /// Access a portion of the slice with bounds checking. If the access is not
1082    /// within the slice then `None` is returned.
1083    pub fn get<I: ProcessSliceIndex<Self>>(
1084        &self,
1085        index: I,
1086    ) -> Option<&<I as ProcessSliceIndex<Self>>::Output> {
1087        index.get(self)
1088    }
1089
1090    /// Access a portion of the slice with bounds checking. If the access is not
1091    /// within the slice then `None` is returned.
1092    #[deprecated = "Use WriteableProcessSlice::get instead"]
1093    pub fn get_from(&self, range: RangeFrom<usize>) -> Option<&WriteableProcessSlice> {
1094        range.get(self)
1095    }
1096
1097    /// Access a portion of the slice with bounds checking. If the access is not
1098    /// within the slice then `None` is returned.
1099    #[deprecated = "Use WriteableProcessSlice::get instead"]
1100    pub fn get_to(&self, range: RangeTo<usize>) -> Option<&WriteableProcessSlice> {
1101        range.get(self)
1102    }
1103}
1104
1105impl ProcessSliceIndex<WriteableProcessSlice> for usize {
1106    type Output = Cell<u8>;
1107
1108    fn get(self, slice: &WriteableProcessSlice) -> Option<&Self::Output> {
1109        slice.slice.get(self)
1110    }
1111
1112    fn index(self, slice: &WriteableProcessSlice) -> &Self::Output {
1113        &slice.slice[self]
1114    }
1115}
1116
1117impl ProcessSliceIndex<WriteableProcessSlice> for Range<usize> {
1118    type Output = WriteableProcessSlice;
1119
1120    fn get(self, slice: &WriteableProcessSlice) -> Option<&Self::Output> {
1121        slice.slice.get(self).map(cast_cell_slice_to_process_slice)
1122    }
1123
1124    fn index(self, slice: &WriteableProcessSlice) -> &Self::Output {
1125        cast_cell_slice_to_process_slice(&slice.slice[self])
1126    }
1127}
1128
1129impl ProcessSliceIndex<WriteableProcessSlice> for RangeFrom<usize> {
1130    type Output = WriteableProcessSlice;
1131
1132    fn get(self, slice: &WriteableProcessSlice) -> Option<&Self::Output> {
1133        slice.slice.get(self).map(cast_cell_slice_to_process_slice)
1134    }
1135
1136    fn index(self, slice: &WriteableProcessSlice) -> &Self::Output {
1137        cast_cell_slice_to_process_slice(&slice.slice[self])
1138    }
1139}
1140
1141impl ProcessSliceIndex<WriteableProcessSlice> for RangeTo<usize> {
1142    type Output = WriteableProcessSlice;
1143
1144    fn get(self, slice: &WriteableProcessSlice) -> Option<&Self::Output> {
1145        slice.slice.get(self).map(cast_cell_slice_to_process_slice)
1146    }
1147
1148    fn index(self, slice: &WriteableProcessSlice) -> &Self::Output {
1149        cast_cell_slice_to_process_slice(&slice.slice[self])
1150    }
1151}
1152
1153impl<I: ProcessSliceIndex<Self>> Index<I> for WriteableProcessSlice {
1154    type Output = I::Output;
1155
1156    fn index(&self, index: I) -> &Self::Output {
1157        index.index(self)
1158    }
1159}