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);