Similar to bitmap.rs, add hardening to print errors or assert if the setter API is used to write out-of-bound values.
Suggested-by: Yury Norov <[email protected]> Signed-off-by: Joel Fernandes <[email protected]> --- rust/kernel/bitfield.rs | 32 +++++++++++++++++++++++++++++++- security/Kconfig.hardening | 9 +++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/rust/kernel/bitfield.rs b/rust/kernel/bitfield.rs index a74e6d45ecd3..655f940479f1 100644 --- a/rust/kernel/bitfield.rs +++ b/rust/kernel/bitfield.rs @@ -29,6 +29,20 @@ pub const fn into_raw(self) -> T { } } +/// Assertion macro for bitfield +#[macro_export] +macro_rules! bitfield_assert { + ($cond:expr, $($arg:tt)+) => { + #[cfg(CONFIG_RUST_BITFIELD_HARDENED)] + ::core::assert!($cond, $($arg)*); + + #[cfg(not(CONFIG_RUST_BITFIELD_HARDENED))] + if !($cond) { + $crate::pr_err!($($arg)+); + } + } +} + /// Bitfield macro definition. /// Define a struct with accessors to access bits within an inner unsigned integer. /// @@ -358,9 +372,25 @@ impl $name { $vis fn [<set_ $field>](mut self, value: $to_type) -> Self { const MASK: $storage = $name::[<$field:upper _MASK>]; const SHIFT: u32 = $name::[<$field:upper _SHIFT>]; + const BITS: u32 = ($hi - $lo + 1) as u32; + const MAX_VALUE: $storage = + if BITS >= (::core::mem::size_of::<$storage>() * 8) as u32 { + !0 + } else { + (1 << BITS) - 1 + }; + + // Check for overflow - value should fit within the field's bits. // Here we are potentially narrowing value from a wider bit value // to a narrower bit value. So we have to use `as` instead of `::from()`. - let val = ((value as $storage) << SHIFT) & MASK; + let raw_field_value = value as $storage; + + $crate::bitfield_assert!( + raw_field_value <= MAX_VALUE, + "value {} exceeds {} for a {} bit field", raw_field_value, MAX_VALUE, BITS + ); + + let val = (raw_field_value << SHIFT) & MASK; let new_val = (self.raw() & !MASK) | val; self.0 = ::kernel::bitfield::BitfieldInternalStorage::from_raw(new_val); diff --git a/security/Kconfig.hardening b/security/Kconfig.hardening index 86f8768c63d4..e9fc6dcbd6c3 100644 --- a/security/Kconfig.hardening +++ b/security/Kconfig.hardening @@ -265,6 +265,15 @@ config RUST_BITMAP_HARDENED If unsure, say N. +config RUST_BITFIELD_HARDENED + bool "Check integrity of bitfield Rust API" + depends on RUST + help + Enables additional assertions in the Rust Bitfield API to catch + values that exceed the bitfield bounds. + + If unsure, say N. + config BUG_ON_DATA_CORRUPTION bool "Trigger a BUG when data corruption is detected" select LIST_HARDENED -- 2.34.1
