linux-kpi: P2 transmute audit — add SAFETY comments, type safety
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<usize,usize> 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.
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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::<usize, extern "C" fn(c_ulong)>(function_addr) };
|
||||
function(data_addr as c_ulong);
|
||||
|
||||
Reference in New Issue
Block a user