* [PATCH v4] rust: kernel: introduce `unsafe_precondition_assert!` macro
@ 2025-08-08 19:17 Ritvik Gupta
2025-08-11 9:19 ` Alice Ryhl
` (2 more replies)
0 siblings, 3 replies; 6+ messages in thread
From: Ritvik Gupta @ 2025-08-08 19:17 UTC (permalink / raw)
To: Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl,
Trevor Gross, Danilo Krummrich
Cc: linux-kernel, rust-for-linux
Introduce a new `safety` module containing `unsafe_precondition_assert!`
macro. It is a wrapper around `debug_assert!`, intended for validating
pre-conditions of unsafe function.
When `CONFIG_RUST_DEBUG_ASSERTIONS` flag is enabled, this macro performs
runtime checks to ensure that the preconditions for unsafe function hold.
Otherwise, the macro is a no-op.
Suggested-by: Miguel Ojeda <ojeda@kernel.org>
Link: https://github.com/Rust-for-Linux/linux/issues/1162
Link: https://rust-for-linux.zulipchat.com/#narrow/channel/291566-Library/topic/.60unsafe_precondition_assert.60.20macro/with/528457452
Signed-off-by: Ritvik Gupta <ritvikfoss@gmail.com>
---
Changes in v4:
- Change doc example
- Add `no_run` attribute to the doc example
- Link to v3: https://lore.kernel.org/rust-for-linux/20250731111234.28602-1-ritvikfoss@gmail.com/
Changes in v3:
- Change doc example
- Link to v2: https://lore.kernel.org/all/20250730181420.6979b4f1@eugeo/T/#m9cd35a8fc02a18bd03934c7ecdcffe8667b5fbbd
Changes in v2:
- Wrap `debug_assert!` internally instead of using `pr_err!` with `assert!` + `cfg!(debug_assertions)
- Print “unsafe precondition(s) violated” only on assertion failure (no longer always printed)
- Use `# Safety` section instead of comment in the example
- Rename module-level doc
- Link to v1: https://lore.kernel.org/rust-for-linux/20250716045957.39732-1-ritvikfoss@gmail.com/
---
rust/kernel/lib.rs | 1 +
rust/kernel/safety.rs | 48 +++++++++++++++++++++++++++++++++++++++++++
2 files changed, 49 insertions(+)
create mode 100644 rust/kernel/safety.rs
diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs
index ed53169e795c..5eb301685ce8 100644
--- a/rust/kernel/lib.rs
+++ b/rust/kernel/lib.rs
@@ -113,6 +113,7 @@
pub mod rbtree;
pub mod regulator;
pub mod revocable;
+pub mod safety;
pub mod security;
pub mod seq_file;
pub mod sizes;
diff --git a/rust/kernel/safety.rs b/rust/kernel/safety.rs
new file mode 100644
index 000000000000..880307a5fbf4
--- /dev/null
+++ b/rust/kernel/safety.rs
@@ -0,0 +1,48 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! Safety related APIs.
+
+/// Checks that preconditions of an unsafe function are followed.
+///
+/// The check is enabled at runtime if debug assertions (`CONFIG_RUST_DEBUG_ASSERTIONS`)
+/// are enabled. Otherwise, this macro is no-op.
+///
+/// # Examples
+///
+/// ```no_run
+/// # use kernel::unsafe_precondition_assert;
+/// # use kernel::cpu::{nr_cpu_ids, CpuId};
+/// /// Creates a [`CpuId`] from the given `id` without bound checks.
+/// ///
+/// /// # Safety
+/// ///
+/// /// The caller must ensure that `id` is a valid CPU ID (i.e, `0 <= id < nr_cpu_ids()`).
+/// unsafe fn new_cpu_id_unchecked(id: i32) -> CpuId {
+/// let max_cpus = nr_cpu_ids();
+///
+/// unsafe_precondition_assert!(id >= 0, "id ({}) must be positive", id);
+///
+/// unsafe_precondition_assert!(
+/// id < max_cpus, "id ({}) must be less than total CPUs ({})", id, max_cpus
+/// );
+///
+/// CpuId(id)
+/// }
+/// ```
+///
+/// # Panics
+///
+/// Panics if the expression is evaluated to `false` at runtime.
+#[macro_export]
+macro_rules! unsafe_precondition_assert {
+ ($cond:expr $(,)?) => {
+ $crate::unsafe_precondition_assert!(@inner $cond, ::core::stringify!($cond))
+ };
+
+ ($cond:expr, $($arg:tt)+) => {
+ $crate::unsafe_precondition_assert!(@inner $cond, ::core::format_args!($($arg)+))
+ };
+
+ (@inner $cond:expr, $msg:expr) => {
+ ::core::debug_assert!($cond, "unsafe precondition(s) violated: {}", $msg) };
+}
base-commit: 37816488247ddddbc3de113c78c83572274b1e2e
--
2.50.1
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH v4] rust: kernel: introduce `unsafe_precondition_assert!` macro
2025-08-08 19:17 [PATCH v4] rust: kernel: introduce `unsafe_precondition_assert!` macro Ritvik Gupta
@ 2025-08-11 9:19 ` Alice Ryhl
2025-08-11 11:40 ` Ritvik Gupta
2025-08-12 15:52 ` kernel test robot
2025-08-12 21:26 ` Ritvik Gupta
2 siblings, 1 reply; 6+ messages in thread
From: Alice Ryhl @ 2025-08-11 9:19 UTC (permalink / raw)
To: Ritvik Gupta, Tamir Duberstein
Cc: Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
Björn Roy Baron, Benno Lossin, Andreas Hindborg,
Trevor Gross, Danilo Krummrich, linux-kernel, rust-for-linux
On Sat, Aug 09, 2025 at 12:47:49AM +0530, Ritvik Gupta wrote:
> Introduce a new `safety` module containing `unsafe_precondition_assert!`
> macro. It is a wrapper around `debug_assert!`, intended for validating
> pre-conditions of unsafe function.
>
> When `CONFIG_RUST_DEBUG_ASSERTIONS` flag is enabled, this macro performs
> runtime checks to ensure that the preconditions for unsafe function hold.
> Otherwise, the macro is a no-op.
>
> Suggested-by: Miguel Ojeda <ojeda@kernel.org>
> Link: https://github.com/Rust-for-Linux/linux/issues/1162
> Link: https://rust-for-linux.zulipchat.com/#narrow/channel/291566-Library/topic/.60unsafe_precondition_assert.60.20macro/with/528457452
> Signed-off-by: Ritvik Gupta <ritvikfoss@gmail.com>
> + ($cond:expr, $($arg:tt)+) => {
> + $crate::unsafe_precondition_assert!(@inner $cond, ::core::format_args!($($arg)+))
Tamir, taking your fmt series into account, what's the correct
replacement for ::core::format_args! here?
Alice
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH v4] rust: kernel: introduce `unsafe_precondition_assert!` macro
2025-08-11 9:19 ` Alice Ryhl
@ 2025-08-11 11:40 ` Ritvik Gupta
0 siblings, 0 replies; 6+ messages in thread
From: Ritvik Gupta @ 2025-08-11 11:40 UTC (permalink / raw)
To: Alice Ryhl
Cc: Tamir Duberstein, Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
Björn Roy Baron, Benno Lossin, Andreas Hindborg,
Trevor Gross, Danilo Krummrich, linux-kernel, rust-for-linux
> > + ($cond:expr, $($arg:tt)+) => {
> > + $crate::unsafe_precondition_assert!(@inner $cond, ::core::format_args!($($arg)+))
>
> Tamir, taking your fmt series into account, what's the correct
> replacement for ::core::format_args! here?
Whoops! I wasn't aware of the fmt-series! Thanks for mentioning it :)
After a quick search, `kernel::prelude::fmt!` type/macro [1,2] seems to be the relevant replacement.
So, the line would look like:
`$crate::unsafe_precondition_assert!(@inner $cond, $crate::prelude::fmt!($($arg)+))`
Does that sound right?
[1]: https://github.com/Rust-for-Linux/linux/blob/8f5ae30d69d7543eee0d70083daf4de8fe15d585/rust/kernel/prelude.rs#L36
[2]: https://lore.kernel.org/rust-for-linux/20250719-core-cstr-fanout-1-v2-4-1ab5ba189c6e@gmail.com/
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH v4] rust: kernel: introduce `unsafe_precondition_assert!` macro
2025-08-08 19:17 [PATCH v4] rust: kernel: introduce `unsafe_precondition_assert!` macro Ritvik Gupta
2025-08-11 9:19 ` Alice Ryhl
@ 2025-08-12 15:52 ` kernel test robot
2025-08-12 18:08 ` Ritvik Gupta
2025-08-12 21:26 ` Ritvik Gupta
2 siblings, 1 reply; 6+ messages in thread
From: kernel test robot @ 2025-08-12 15:52 UTC (permalink / raw)
To: Ritvik Gupta, Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl,
Trevor Gross, Danilo Krummrich
Cc: llvm, oe-kbuild-all, linux-kernel, rust-for-linux
Hi Ritvik,
kernel test robot noticed the following build errors:
[auto build test ERROR on 37816488247ddddbc3de113c78c83572274b1e2e]
url: https://github.com/intel-lab-lkp/linux/commits/Ritvik-Gupta/rust-kernel-introduce-unsafe_precondition_assert-macro/20250809-032122
base: 37816488247ddddbc3de113c78c83572274b1e2e
patch link: https://lore.kernel.org/r/20250808192005.209188-1-ritvikfoss%40gmail.com
patch subject: [PATCH v4] rust: kernel: introduce `unsafe_precondition_assert!` macro
config: x86_64-rhel-9.4-rust (https://download.01.org/0day-ci/archive/20250812/202508122341.rb7U1Q2P-lkp@intel.com/config)
compiler: clang version 20.1.8 (https://github.com/llvm/llvm-project 87f0227cb60147a26a1eeb4fb06e3b505e9c7261)
rustc: rustc 1.88.0 (6b00bc388 2025-06-23)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250812/202508122341.rb7U1Q2P-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202508122341.rb7U1Q2P-lkp@intel.com/
All errors (new ones prefixed by >>):
>> error[E0423]: cannot initialize a tuple struct which contains private fields
--> rust/doctests_kernel_generated.rs:8841:5
|
8841 | CpuId(id)
| ^^^^^
|
note: constructor is not visible here due to private fields
--> rust/kernel/cpu.rs:47:18
|
47 | pub struct CpuId(u32);
| ^^^ private field
help: you might have meant to use an associated function to build this type
|
8841 - CpuId(id)
8841 + CpuId::from_i32_unchecked(_)
|
8841 - CpuId(id)
8841 + CpuId::from_u32_unchecked(_)
|
8841 - CpuId(id)
8841 + CpuId::current()
|
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH v4] rust: kernel: introduce `unsafe_precondition_assert!` macro
2025-08-12 15:52 ` kernel test robot
@ 2025-08-12 18:08 ` Ritvik Gupta
0 siblings, 0 replies; 6+ messages in thread
From: Ritvik Gupta @ 2025-08-12 18:08 UTC (permalink / raw)
To: kernel test robot
Cc: Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl,
Trevor Gross, Danilo Krummrich, llvm, oe-kbuild-all, linux-kernel,
rust-for-linux
If someone's referring to it in the future, this was doctest issue.
It’s actually the second time I’ve hit it.
On my end, this error wasn't occurring when compiling the kernel.
What I was missing:
1. Enable `Kernel Hacking > Kernel Testing and Coverage > KUnit`
2. Enable Doctest in `Rust hacking > Doctests for the 'kernel' crate`
I can now reproduce capture the issue locally.
Won't happen again :)
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH v4] rust: kernel: introduce `unsafe_precondition_assert!` macro
2025-08-08 19:17 [PATCH v4] rust: kernel: introduce `unsafe_precondition_assert!` macro Ritvik Gupta
2025-08-11 9:19 ` Alice Ryhl
2025-08-12 15:52 ` kernel test robot
@ 2025-08-12 21:26 ` Ritvik Gupta
2 siblings, 0 replies; 6+ messages in thread
From: Ritvik Gupta @ 2025-08-12 21:26 UTC (permalink / raw)
To: Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl,
Trevor Gross, Danilo Krummrich
Cc: linux-kernel, rust-for-linux
> +/// # Examples
> +///
> +/// ```no_run
> +/// # use kernel::unsafe_precondition_assert;
> +/// # use kernel::cpu::{nr_cpu_ids, CpuId};
> +/// /// Creates a [`CpuId`] from the given `id` without bound checks.
> +/// ///
> +/// /// # Safety
> +/// ///
> +/// /// The caller must ensure that `id` is a valid CPU ID (i.e, `0 <= id < nr_cpu_ids()`).
> +/// unsafe fn new_cpu_id_unchecked(id: i32) -> CpuId {
> +/// let max_cpus = nr_cpu_ids();
> +///
> +/// unsafe_precondition_assert!(id >= 0, "id ({}) must be positive", id);
> +///
> +/// unsafe_precondition_assert!(
> +/// id < max_cpus, "id ({}) must be less than total CPUs ({})", id, max_cpus
> +/// );
> +///
> +/// CpuId(id)
> +/// }
> +/// ```
The example I've included is incorrect because `CpuId` inner field is private,
so it can't be constructed this way.
`CpuId::from_i32_unchecked()` exists, using it here would make the example a
trivial wrapper around that method, that would be unnecessary and confusing.
Also, I wasn't sure about the doctest config when I wrote it.
I'll send v5 with correct and much better example.
Plz ignore it. Sorry for the noise.
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2025-08-12 21:25 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-08-08 19:17 [PATCH v4] rust: kernel: introduce `unsafe_precondition_assert!` macro Ritvik Gupta
2025-08-11 9:19 ` Alice Ryhl
2025-08-11 11:40 ` Ritvik Gupta
2025-08-12 15:52 ` kernel test robot
2025-08-12 18:08 ` Ritvik Gupta
2025-08-12 21:26 ` Ritvik Gupta
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).