From 3388b5cecf95d6b0bc9cf5c952e9f0aa1e019b8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mattias=20Gr=C3=B6nlund?= Date: Tue, 9 Aug 2022 00:53:32 +0200 Subject: [PATCH] Improve data checks for VHD events For some reason I got strange events on channel 1 (ASYNCEVENT_HEADER): 0.647329 WARN unexpected ehternet type 0x0508, expected Qualcom ether type 0x886c This patch improves the validation of BCD WHD events to minimize the risk for panic. --- src/events.rs | 1 + src/lib.rs | 53 +++++++++++++++++++++++++++++++++++++++-------- src/structs.rs | 56 ++++++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 99 insertions(+), 11 deletions(-) diff --git a/src/events.rs b/src/events.rs index b35b12fa..a828eec9 100644 --- a/src/events.rs +++ b/src/events.rs @@ -1,4 +1,5 @@ #![allow(unused)] +#![allow(non_camel_case_types)] use core::num; diff --git a/src/lib.rs b/src/lib.rs index 133ce316..3d08370c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -815,20 +815,55 @@ where trace!(" {:?}", bcd_header); let packet_start = BcdHeader::SIZE + 4 * bcd_header.data_offset as usize; - if packet_start > payload.len() { - warn!("packet start out of range."); + + if packet_start + EventPacket::SIZE > payload.len() { + warn!("BCD event, incomplete header"); return; } - let packet = &payload[packet_start..]; - trace!(" {:02x}", &packet[..(packet.len() as usize).min(36)]); + let bcd_packet = &payload[packet_start..]; + trace!(" {:02x}", &bcd_packet[..(bcd_packet.len() as usize).min(36)]); - let mut evt = EventHeader::from_bytes(&packet[24..][..EventHeader::SIZE].try_into().unwrap()); - evt.byteswap(); - let evt_data = &packet[24 + EventHeader::SIZE..][..evt.datalen as usize]; + let mut event_packet = EventPacket::from_bytes(&bcd_packet[..EventPacket::SIZE].try_into().unwrap()); + event_packet.byteswap(); + + const ETH_P_LINK_CTL: u16 = 0x886c; // HPNA, wlan link local tunnel, according to linux if_ether.h + if event_packet.eth.ether_type != ETH_P_LINK_CTL { + warn!( + "unexpected ethernet type 0x{:04x}, expected Broadcom ether type 0x{:04x}", + event_packet.eth.ether_type, ETH_P_LINK_CTL + ); + return; + } + const BROADCOM_OUI: &[u8] = &[0x00, 0x10, 0x18]; + if event_packet.hdr.oui != BROADCOM_OUI { + warn!( + "unexpected ethernet OUI {:02x}, expected Broadcom OUI {:02x}", + event_packet.hdr.oui, BROADCOM_OUI + ); + return; + } + const BCMILCP_SUBTYPE_VENDOR_LONG: u16 = 32769; + if event_packet.hdr.subtype != BCMILCP_SUBTYPE_VENDOR_LONG { + warn!("unexpected subtype {}", event_packet.hdr.subtype); + return; + } + + const BCMILCP_BCM_SUBTYPE_EVENT: u16 = 1; + if event_packet.hdr.user_subtype != BCMILCP_BCM_SUBTYPE_EVENT { + warn!("unexpected user_subtype {}", event_packet.hdr.subtype); + return; + } + + if event_packet.msg.datalen as usize >= (bcd_packet.len() - EventMessage::SIZE) { + warn!("BCD event, incomplete data"); + return; + } + + let evt_data = &bcd_packet[EventMessage::SIZE..][..event_packet.msg.datalen as usize]; debug!( "=== EVENT {}: {} {:02x}", - events::Event::from(evt.event_type as u8), - evt, + events::Event::from(event_packet.msg.event_type as u8), + event_packet.msg, evt_data ); } diff --git a/src/structs.rs b/src/structs.rs index 060c2b06..7a7c25b2 100644 --- a/src/structs.rs +++ b/src/structs.rs @@ -64,10 +64,44 @@ pub struct BcdHeader { } impl_bytes!(BcdHeader); +#[derive(Clone, Copy)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[repr(C)] +pub struct EthernetHeader { + pub destination_mac: [u8; 6], + pub source_mac: [u8; 6], + pub ether_type: u16, +} + +impl EthernetHeader { + pub fn byteswap(&mut self) { + self.ether_type = self.ether_type.to_be(); + } +} + #[derive(Clone, Copy)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] #[repr(C)] pub struct EventHeader { + pub subtype: u16, + pub length: u16, + pub version: u8, + pub oui: [u8; 3], + pub user_subtype: u16, +} + +impl EventHeader { + pub fn byteswap(&mut self) { + self.subtype = self.subtype.to_be(); + self.length = self.length.to_be(); + self.user_subtype = self.user_subtype.to_be(); + } +} + +#[derive(Clone, Copy)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[repr(C)] +pub struct EventMessage { /// version pub version: u16, /// see flags below @@ -91,9 +125,9 @@ pub struct EventHeader { /// source bsscfg index pub bsscfgidx: u8, } -impl_bytes!(EventHeader); +impl_bytes!(EventMessage); -impl EventHeader { +impl EventMessage { pub fn byteswap(&mut self) { self.version = self.version.to_be(); self.flags = self.flags.to_be(); @@ -105,6 +139,24 @@ impl EventHeader { } } +#[derive(Clone, Copy)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[repr(C)] +pub struct EventPacket { + pub eth: EthernetHeader, + pub hdr: EventHeader, + pub msg: EventMessage, +} +impl_bytes!(EventPacket); + +impl EventPacket { + pub fn byteswap(&mut self) { + self.eth.byteswap(); + self.hdr.byteswap(); + self.msg.byteswap(); + } +} + #[derive(Clone, Copy)] #[repr(C)] pub struct DownloadHeader {