[Deepin-Kernel-SIG] [linux 6.18.y] [FROMLIST] [Security] rust: add untrusted data API with Validate trait and defconfig updates#1754
Conversation
Add CONFIG_RUST=y to the deepin desktop defconfig files for arm64, loongarch, s390x, and x86 architectures to enable kernel Rust support. Please note that the deepin kernel still defaults to building with GCC. Make sure all CI environments are configured so that running "make rustavailable" prints "Rust is available!". Signed-off-by: WangYuli <wangyl5933@chinaunicom.cn>
Add functions to make casting slices only one `unsafe` block. Signed-off-by: Benno Lossin <benno.lossin@proton.me> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Link: https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core.git/commit/?h=untrusted&id=24faf69bdc54e056621786f4c48bc6cd15c3cbf6 Signed-off-by: WangYuli <wangyl5933@chinaunicom.cn>
When the kernel receives external data (e.g. from userspace), it usually is a very bad idea to directly use the data for logic decision in the kernel. For this reason, such data should be explicitly marked and validated before making decision based on its value. The `Untrusted<T>` wrapper type marks a value of type `T` as untrusted. The particular meaning of "untrusted" highly depends on the type `T`. For example `T = u8` ensures that the value of the byte cannot be retrieved. However, `T = [u8]` still allows to access the length of the slice. Similarly, `T = KVec<U>` allows modifications. Signed-off-by: Benno Lossin <benno.lossin@proton.me> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> [WangYuli: Fix conflicts] Link: https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core.git/commit/?h=untrusted&id=3937bad8a8bf2e5d7fc3e11b4ed1aae21df71b02 Signed-off-by: WangYuli <wangyl5933@chinaunicom.cn>
Introduce the `Validate<Input>` trait and functions to validate
`Untrusted<T>` using said trait. This allows one to access the inner
value of `Untrusted<T>` via `validate{,_ref,_mut}` functions which
subsequently delegate the validation to user-implemented `Validate`
trait.
The `Validate` trait is the only entry point for validation code, making
it easy to spot where data is being validated.
The reason for restricting the types that can be inputs to
`Validate::validate` is to be able to have the `validate...` functions
on `Untrusted`. This is also the reason for the suggestions in the
`Usage in API Design` section in the commit that introduced
`Untrusted<T>`.
Signed-off-by: Benno Lossin <benno.lossin@proton.me>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Link: https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core.git/commit/?h=untrusted&id=4de2ce9189dcc45103f39fcc3e55eb1d792cf51b
Signed-off-by: WangYuli <wangyl5933@chinaunicom.cn>
Reviewer's GuideIntroduces a Rust "untrusted data" API centered around a new Untrusted wrapper and Validate trait, adds safe slice casting helpers in transmute, wires the new module into the Rust kernel crate, and updates deepin defconfigs for Rust support. File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
|
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: The full list of commands accepted by this bot can be found here. DetailsNeeds approval from an approver in each of these files:Approvers can indicate their approval by writing |
fb8a0c2 to
1dcbb6d
Compare
There was a problem hiding this comment.
Hey - I've found 1 issue
Prompt for AI Agents
Please address the comments from this code review:
## Individual Comments
### Comment 1
<location path="rust/kernel/validate.rs" line_range="68-69" />
<code_context>
+/// pub fn read_from_userspace(buf: &mut Untrusted<[u8]>) { todo!() }
+/// ```
+///
+/// The reason for this is that `&mut Untrusted<[u8]>` can beconverted into `&mut [Untrusted<u8>]`
+/// very easily, but the converse is not possible.
+///
</code_context>
<issue_to_address>
**nitpick (typo):** Fix a small documentation typo in the `Untrusted` usage section.
There’s a missing space in "can beconverted"; please change it to "can be converted".
```suggestion
//// The reason for this is that `&mut Untrusted<[u8]>` can be converted into `&mut [Untrusted<u8>]`
/// very easily, but the converse is not possible.
```
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
| /// The reason for this is that `&mut Untrusted<[u8]>` can beconverted into `&mut [Untrusted<u8>]` | ||
| /// very easily, but the converse is not possible. |
There was a problem hiding this comment.
nitpick (typo): Fix a small documentation typo in the Untrusted usage section.
There’s a missing space in "can beconverted"; please change it to "can be converted".
| /// The reason for this is that `&mut Untrusted<[u8]>` can beconverted into `&mut [Untrusted<u8>]` | |
| /// very easily, but the converse is not possible. | |
| //// The reason for this is that `&mut Untrusted<[u8]>` can be converted into `&mut [Untrusted<u8>]` | |
| /// very easily, but the converse is not possible. |
There was a problem hiding this comment.
Pull request overview
Adds a Rust “untrusted data” abstraction to help prevent accidental use of attacker-controlled bytes for kernel logic, and enables Rust support in Deepin defconfigs so the new Rust-side APIs can be built.
Changes:
- Introduce
rust/kernel/validate.rswithUntrusted<T>and aValidatetrait to gate access to untrusted inputs. - Add
cast_slice/cast_slice_muthelpers torust/kernel/transmute.rsto support transparent-wrapper slice casting. - Enable
CONFIG_RUST=yin multiple Deepin arch defconfigs and export the new module viarust/kernel/lib.rs.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| rust/kernel/validate.rs | New untrusted-data wrapper and validation trait intended to prevent logic on unvalidated input. |
| rust/kernel/transmute.rs | Adds slice-casting helpers used by Untrusted deref implementations. |
| rust/kernel/lib.rs | Exposes the new validate module. |
| arch/x86/configs/deepin_x86_desktop_defconfig | Enables Rust in the x86 Deepin desktop defconfig. |
| arch/s390/configs/deepin_s390x_z13_defconfig | Enables Rust in the s390x z13 Deepin defconfig. |
| arch/loongarch/configs/deepin_loongarch_desktop_defconfig | Enables Rust in the LoongArch Deepin desktop defconfig. |
| arch/arm64/configs/deepin_arm64_desktop_defconfig | Enables Rust in the arm64 Deepin desktop defconfig. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| /// pub fn read_from_userspace(buf: &mut Untrusted<[u8]>) { todo!() } | ||
| /// ``` | ||
| /// | ||
| /// The reason for this is that `&mut Untrusted<[u8]>` can beconverted into `&mut [Untrusted<u8>]` |
| type Inner: ?Sized; | ||
| } | ||
|
|
||
| impl<T: ?Sized> ValidateInput for Untrusted<T> { |
| /// Casts the type of a slice to another. | ||
| /// | ||
| /// Also see [`cast_slice_mut`]. | ||
| /// | ||
| /// # Examples | ||
| /// | ||
| /// ```rust | ||
| /// # use kernel::transmute::cast_slice; | ||
| /// #[repr(transparent)] | ||
| /// #[derive(Debug)] | ||
| /// struct Container<T>(T); | ||
| /// | ||
| /// let array = [0u32; 42]; | ||
| /// let slice = &array; | ||
| /// // SAFETY: `Container<u32>` transparently wraps a `u32`. | ||
| /// let container_slice = unsafe { cast_slice::<u32, Container<u32>>(slice) }; | ||
| /// pr_info!("{container_slice:?}"); | ||
| /// ``` | ||
| /// | ||
| /// # Safety | ||
| /// | ||
| /// - `T` and `U` must have the same layout. | ||
| pub unsafe fn cast_slice<T, U>(slice: &[T]) -> &[U] { | ||
| // CAST: by the safety requirements, `T` and `U` have the same layout. | ||
| let ptr = slice.as_ptr().cast::<U>(); | ||
| // SAFETY: `ptr` and `len` come from the same slice reference. | ||
| unsafe { slice::from_raw_parts(ptr, slice.len()) } |
| /// Casts the type of a slice to another. | ||
| /// | ||
| /// Also see [`cast_slice`]. | ||
| /// | ||
| /// # Examples | ||
| /// | ||
| /// ```rust | ||
| /// # use kernel::transmute::cast_slice_mut; | ||
| /// #[repr(transparent)] | ||
| /// #[derive(Debug)] | ||
| /// struct Container<T>(T); | ||
| /// | ||
| /// let mut array = [0u32; 42]; | ||
| /// let slice = &mut array; | ||
| /// // SAFETY: `Container<u32>` transparently wraps a `u32`. | ||
| /// let container_slice = unsafe { cast_slice_mut::<u32, Container<u32>>(slice) }; | ||
| /// pr_info!("{container_slice:?}"); | ||
| /// ``` | ||
| /// | ||
| /// # Safety | ||
| /// | ||
| /// - `T` and `U` must have the same layout. | ||
| pub unsafe fn cast_slice_mut<T, U>(slice: &mut [T]) -> &mut [U] { | ||
| // CAST: by the safety requirements, `T` and `U` have the same layout. | ||
| let ptr = slice.as_mut_ptr().cast::<U>(); | ||
| // SAFETY: `ptr` and `len` come from the same slice reference. | ||
| unsafe { slice::from_raw_parts_mut(ptr, slice.len()) } | ||
| } |
Please note that the deepin kernel still defaults to building with GCC. Make sure all CI environments are configured so that running
make rustavailableprintsRust is available!.Summary by Sourcery
Introduce a Rust untrusted data abstraction and related utilities for safely handling and validating data from untrusted sources.
New Features: