rust: kernel: introduce `unsafe_precondition_assert!` macro
PATCH v3 1/1 rust: kernel: introduce `unsafe_precondition_assert!` macro
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.
---
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/[email protected]/
--- rust/kernel/lib.rs | 1 + rust/kernel/safety.rs | 47 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+) create mode 100644 rust/kernel/safety.rs
rust/kernel/lib.rs +1 -0
@@ -104,6 +104,7 @@pub mod print;pub mod rbtree;pub mod revocable; +pub mod safety;pub mod security;pub mod seq_file;pub mod sizes;
rust/kernel/safety.rs new file +47 -0
47 lines not on this page · raw message
base-commit: dff64b072708ffef23c117fa1ee1ea59eb417807
Signature · 1 line
2.50.1
rust/kernel/safety.rs line 16
Quoted 3 lines · Ritvik Gupta
rust/kernel/safety.rs new file +2
-0+/// /// - `buf` must be non-null. +/// /// - `buf` must be 16-byte aligned.
We don't know since the full body is not shown, but it is likely this would need to also be a valid pointer, i.e. it may be an uncommon example.
Perhaps we could show one of the conditional cases, i.e. the "if buf is non-null, then it must be valid." cases. That could also be a nice excuse to also introduce an implies() function if an example allows for it. But we can do that later on, no worries.
More importantly, could we have a user of the macro introduced in a second patch so that it gets already used?
Thanks for the patch!
Cheers,
Miguel
Quoted 8 lines · Miguel Ojeda
rust/kernel/safety.rs line 16
Quoted 3 lines · Ritvik Gupta
rust/kernel/safety.rs new file +2
-0+/// /// - `buf` must be non-null. +/// /// - `buf` must be 16-byte aligned. We don't know since the full body is not shown, but it is likely this would need to also be a valid pointer, i.e. it may be an uncommon example.
I believe this is a valid use-case for unsafe_precondition_assert!. Should we add similar example?
```cpu.rs
/// Creates a new [`CpuId`] from the given `id` without checking bounds.
///
/// # Safety
///
/// The caller must ensure that `id` is a valid CPU ID (i.e., `0 <= id < nr_cpu_ids()`).
#[inline]
pub unsafe fn from_u32_unchecked(id: u32) -> Self {
debug_assert!(id < nr_cpu_ids());
// Ensure the `id` fits in an [`i32`] as it's also representable that way.
debug_assert!(id <= i32::MAX as u32);
// INVARIANT: The function safety guarantees `id` is a valid CPU id.
Self(id)
}
```Quoted 2 lines
More importantly, could we have a user of the macro introduced in a second patch so that it gets already used?
I believe the debug_assert! calls inside the unsafe fn (excluding 'const fn' and 'CONFIG_RUST_OVERFLOW_CHECKS' flag) are the intended targets for unsafe_precondition_assert!.
A quick grep (git grep -B 15 -A 10 "debug_assert"),
I could find 6 relevant callers in alloc/kvec.rs (2) and cpu.rs (4), unless I'm missing something.
I'll send another patch for this, after getting the example correct. Thanks for the feedback :)
kernel test robot
build botkernel test robot noticed the following build errors:
Hi Ritvik,
kernel test robot noticed the following build errors:
[auto build test ERROR on dff64b072708ffef23c117fa1ee1ea59eb417807]
url: https://github.com/intel-lab-lkp/linux/commits/Ritvik-Gupta/rust-kernel-introduce-unsafe_precondition_assert-macro/20250731-191444 base: dff64b072708ffef23c117fa1ee1ea59eb417807 patch link: https://lore.kernel.org/r/20250731111234.28602-1-ritvikfoss%40gmail.com patch subject: [PATCH v3] rust: kernel: introduce `unsafe_precondition_assert!` macro config: x86_64-rhel-9.4-rust (https://download.01.org/0day-ci/archive/20250805/[email protected]/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/20250805/[email protected]/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 <[email protected]>
| Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/
All errors (new ones prefixed by >>):
>> error: cannot find macro `unsafe_precondition_assert` in this scope
--> rust/doctests_kernel_generated.rs:8012:5
|
8012 | unsafe_precondition_assert!(!buf.is_null(), "buf must not be null");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
::: /opt/cross/rustc-1.88.0-bindgen-0.72.0/rustup/toolchains/1.88.0-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ub_checks.rs:52:1 |
52 | macro_rules! assert_unsafe_precondition {
| --------------------------------------- similarly named macro assert_unsafe_precondition defined here
|
help: a macro with a similar name exists
|
8012 - unsafe_precondition_assert!(!buf.is_null(), "buf must not be null");
8012 + assert_unsafe_precondition!(!buf.is_null(), "buf must not be null");
|
help: consider importing this macro
|
3 + use kernel::unsafe_precondition_assert;
|
--
>> error: cannot find macro `unsafe_precondition_assert` in this scope
--> rust/doctests_kernel_generated.rs:8013:5
|
8013 | unsafe_precondition_assert!((buf as usize) % 16 == 0, "buf must be 16-byte aligned");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
::: /opt/cross/rustc-1.88.0-bindgen-0.72.0/rustup/toolchains/1.88.0-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ub_checks.rs:52:1 |
52 | macro_rules! assert_unsafe_precondition {
| --------------------------------------- similarly named macro assert_unsafe_precondition defined here
|
help: a macro with a similar name exists
|
8013 - unsafe_precondition_assert!((buf as usize) % 16 == 0, "buf must be 16-byte aligned");
8013 + assert_unsafe_precondition!((buf as usize) % 16 == 0, "buf must be 16-byte aligned");
|
help: consider importing this macro
|
3 + use kernel::unsafe_precondition_assert;
|
--
>> error: cannot find macro `unsafe_precondition_assert` in this scope
--> rust/doctests_kernel_generated.rs:8014:5
|
8014 | unsafe_precondition_assert!(
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
::: /opt/cross/rustc-1.88.0-bindgen-0.72.0/rustup/toolchains/1.88.0-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ub_checks.rs:52:1 |
52 | macro_rules! assert_unsafe_precondition {
| --------------------------------------- similarly named macro assert_unsafe_precondition defined here
|
help: a macro with a similar name exists
|
8014 - unsafe_precondition_assert!(
8014 + assert_unsafe_precondition!(
|
help: consider importing this macro
|
3 + use kernel::unsafe_precondition_assert;
|
Signature · 2 lines
0-DAY CI Kernel Test Service https://github.com/intel/lkp-tests/wiki