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.
This commit is contained in:
Mattias Grönlund 2022-08-09 00:53:32 +02:00 committed by Dario Nieuwenhuis
parent ddfbfa0132
commit 3388b5cecf
3 changed files with 99 additions and 11 deletions

View File

@ -1,4 +1,5 @@
#![allow(unused)] #![allow(unused)]
#![allow(non_camel_case_types)]
use core::num; use core::num;

View File

@ -815,20 +815,55 @@ where
trace!(" {:?}", bcd_header); trace!(" {:?}", bcd_header);
let packet_start = BcdHeader::SIZE + 4 * bcd_header.data_offset as usize; 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; return;
} }
let packet = &payload[packet_start..]; let bcd_packet = &payload[packet_start..];
trace!(" {:02x}", &packet[..(packet.len() as usize).min(36)]); trace!(" {:02x}", &bcd_packet[..(bcd_packet.len() as usize).min(36)]);
let mut evt = EventHeader::from_bytes(&packet[24..][..EventHeader::SIZE].try_into().unwrap()); let mut event_packet = EventPacket::from_bytes(&bcd_packet[..EventPacket::SIZE].try_into().unwrap());
evt.byteswap(); event_packet.byteswap();
let evt_data = &packet[24 + EventHeader::SIZE..][..evt.datalen as usize];
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!( debug!(
"=== EVENT {}: {} {:02x}", "=== EVENT {}: {} {:02x}",
events::Event::from(evt.event_type as u8), events::Event::from(event_packet.msg.event_type as u8),
evt, event_packet.msg,
evt_data evt_data
); );
} }

View File

@ -64,10 +64,44 @@ pub struct BcdHeader {
} }
impl_bytes!(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)] #[derive(Clone, Copy)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[repr(C)] #[repr(C)]
pub struct EventHeader { 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 /// version
pub version: u16, pub version: u16,
/// see flags below /// see flags below
@ -91,9 +125,9 @@ pub struct EventHeader {
/// source bsscfg index /// source bsscfg index
pub bsscfgidx: u8, pub bsscfgidx: u8,
} }
impl_bytes!(EventHeader); impl_bytes!(EventMessage);
impl EventHeader { impl EventMessage {
pub fn byteswap(&mut self) { pub fn byteswap(&mut self) {
self.version = self.version.to_be(); self.version = self.version.to_be();
self.flags = self.flags.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)] #[derive(Clone, Copy)]
#[repr(C)] #[repr(C)]
pub struct DownloadHeader { pub struct DownloadHeader {