[PATCH v5 03/23] rust: validate: add `Validate` trait

From: alistair23

Date: Tue Oct 27 2026 - 01:28:46 EST


From: Benno Lossin <benno.lossin@xxxxxxxxx>

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>`.

The `Validate::validate()` function allows additional context to be
passed, which can be used as part of the validation process. For example
comparing data against already negotiated information.

Signed-off-by: Benno Lossin <benno.lossin@xxxxxxxxx>
Message-ID: <20250814124424.516191-4-lossin@xxxxxxxxxx>
Signed-off-by: Alistair Francis <alistair.francis@xxxxxxx>
---
rust/kernel/validate.rs | 85 ++++++++++++++++++++++++++++++++++++++++-
1 file changed, 84 insertions(+), 1 deletion(-)

diff --git a/rust/kernel/validate.rs b/rust/kernel/validate.rs
index 3c1fe37624573..3d1c4107fa8fe 100644
--- a/rust/kernel/validate.rs
+++ b/rust/kernel/validate.rs
@@ -11,6 +11,9 @@
//! APIs that write back into userspace usually allow writing untrusted bytes directly, allowing
//! direct copying of untrusted user data back into userspace without validation.
//!
+//! The only way to access untrusted data is to [`Validate::validate`] it. This is facilitated by
+//! the [`Validate`] trait.
+//!
//! # Rationale
//!
//! When reading data from an untrusted source, it must be validated before it can be used for
@@ -56,7 +59,7 @@
/// untrusted, as it would otherwise violate normal Rust rules. For this reason, one can easily
/// convert that reference to `&[Untrusted<u8>]`. Another such example is `Untrusted<KVec<T>>`, it
/// derefs to `[Untrusted<T>]`. Raw bytes however do not behave in this way, `Untrusted<u8>` is
-/// totally opaque.
+/// totally opaque and one can only access its value by calling [`Untrusted::validate()`].
///
/// # Usage in API Design
///
@@ -119,6 +122,42 @@ pub fn new(value: T) -> Self
{
Self::from(value)
}
+
+ /// Validate the underlying untrusted data.
+ ///
+ /// See the [`Validate`] trait for more information.
+ #[inline]
+ pub fn validate<'c, Context, V: Validate<'c, Self, Context>>(
+ self,
+ context: Context,
+ ) -> Result<V, V::Err>
+ where
+ T: Sized,
+ {
+ V::validate(self.0, context)
+ }
+
+ /// Validate the underlying untrusted data.
+ ///
+ /// See the [`Validate`] trait for more information.
+ #[inline]
+ pub fn validate_ref<'a, 'c, Context, V: Validate<'c, &'a Self, Context>>(
+ &'a self,
+ context: Context,
+ ) -> Result<V, V::Err> {
+ V::validate(&self.0, context)
+ }
+
+ /// Validate the underlying untrusted data.
+ ///
+ /// See the [`Validate`] trait for more information.
+ #[inline]
+ pub fn validate_mut<'a, 'c, Context, V: Validate<'c, &'a mut Self, Context>>(
+ &'a mut self,
+ context: Context,
+ ) -> Result<V, V::Err> {
+ V::validate(&mut self.0, context)
+ }
}

impl<T> Untrusted<T> {
@@ -190,3 +229,47 @@ fn deref_mut(&mut self) -> &mut Self::Target {
Untrusted::from_mut_slice(self.0.as_mut_slice())
}
}
+
+/// Marks valid input for the [`Validate`] trait.
+pub trait ValidateInput: private::Sealed {
+ /// Type of the inner data.
+ type Inner: ?Sized;
+}
+
+impl<T: ?Sized> ValidateInput for Untrusted<T> {
+ type Inner = T;
+}
+
+impl<'a, T: ?Sized> ValidateInput for &'a Untrusted<T> {
+ type Inner = &'a T;
+}
+
+impl<'a, T: ?Sized> ValidateInput for &'a mut Untrusted<T> {
+ type Inner = &'a mut T;
+}
+
+mod private {
+ use super::Untrusted;
+
+ pub trait Sealed {}
+
+ impl<T: ?Sized> Sealed for Untrusted<T> {}
+ impl<'a, T: ?Sized> Sealed for &'a Untrusted<T> {}
+ impl<'a, T: ?Sized> Sealed for &'a mut Untrusted<T> {}
+}
+
+/// Validate [`Untrusted`] data.
+///
+/// Care must be taken when implementing this trait, as unprotected access to unvalidated data is
+/// given to the [`Validate::validate`] function. The implementer must ensure that the data is only
+/// used for logic after successful validation.
+pub trait Validate<'c, Input: ValidateInput, Context>: Sized {
+ /// Validation error.
+ type Err;
+
+ /// Validate the raw input.
+ ///
+ /// `Context` is additional context needed for validation. The `'c` lifetime is the lifetime of
+ /// the borrowed context (`&'c Foo`).
+ fn validate(raw: Input::Inner, context: Context) -> Result<Self, Self::Err>;
+}
--
2.56.0