From f0cb2cbe498e23658dcaf6ec60268211cb415851 Mon Sep 17 00:00:00 2001 From: vasilito Date: Wed, 8 Jul 2026 10:44:19 +0300 Subject: [PATCH] =?UTF-8?q?linux-kpi:=20P2=20transmute=20audit=20=E2=80=94?= =?UTF-8?q?=20add=20SAFETY=20comments,=20type=20safety?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit IMPROVEMENT-PLAN.md §10.3 item 7: HIGH severity transmute audit. mac80211.rs:469: - RxCallback type changed from extern "C" fn to unsafe extern "C" fn - Callback call now wrapped in unsafe { } (correct for FFI callback) - Added SAFETY comment: explains HashMap storage pattern and why usize→fn pointer transmute is sound (same size, valid ABI) timer.rs:202: - Added SAFETY comment: explains Linux kernel timer callback ABI (setup_timer/mod_timer always uses void (*)(unsigned long)) - transmute remains (necessary: usize from C → fn pointer) Both transmutes are now documented with soundness invariants. No actual UB was found — both transmutes were already safe. The fix is documentation, not behavioral change. --- .../linux-kpi/source/src/rust_impl/mac80211.rs | 11 +++++++++-- .../drivers/linux-kpi/source/src/rust_impl/timer.rs | 4 ++++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/local/recipes/drivers/linux-kpi/source/src/rust_impl/mac80211.rs b/local/recipes/drivers/linux-kpi/source/src/rust_impl/mac80211.rs index 9a4dd96084..5b77e3021a 100644 --- a/local/recipes/drivers/linux-kpi/source/src/rust_impl/mac80211.rs +++ b/local/recipes/drivers/linux-kpi/source/src/rust_impl/mac80211.rs @@ -38,7 +38,7 @@ pub struct TxStats { pub nacked: u64, } -pub type RxCallback = extern "C" fn(*mut Ieee80211Hw, *mut SkBuff); +pub type RxCallback = unsafe extern "C" fn(*mut Ieee80211Hw, *mut SkBuff); #[repr(C)] pub struct Ieee80211Ops { @@ -466,8 +466,15 @@ pub extern "C" fn ieee80211_rx_drain(hw: *mut Ieee80211Hw) -> usize { let skb = skb_key as *mut SkBuff; if !skb.is_null() { if let Some(cb) = rx_callback { + // SAFETY: rx_callback is stored as usize from + // ieee80211_register_rx_handler which receives an + // extern "C" fn pointer. The transmute is sound + // because usize and extern "C" fn have the same + // size on all tier-1 platforms, and the stored + // value is always a valid function pointer of the + // correct ABI. let callback: RxCallback = unsafe { std::mem::transmute(cb) }; - callback(hw, skb); + unsafe { callback(hw, skb) }; } else { let skb_ref = unsafe { &mut *skb }; let frame_type = extract_frame_type(skb_ref); diff --git a/local/recipes/drivers/linux-kpi/source/src/rust_impl/timer.rs b/local/recipes/drivers/linux-kpi/source/src/rust_impl/timer.rs index 55f0e0a986..2f019b7aaa 100644 --- a/local/recipes/drivers/linux-kpi/source/src/rust_impl/timer.rs +++ b/local/recipes/drivers/linux-kpi/source/src/rust_impl/timer.rs @@ -198,6 +198,10 @@ pub extern "C" fn mod_timer(timer: *mut TimerList, expires: u64) -> i32 { return; } + // SAFETY: function_addr comes from the Linux kernel timer API + // (setup_timer/mod_timer), which always registers callbacks with + // the signature void (*)(unsigned long). The transmute is sound + // because the C side guarantees the ABI matches. let function = unsafe { std::mem::transmute::(function_addr) }; function(data_addr as c_ulong);