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}