From 7f7f29b4d4f54b0735d3d4250a715db1065f4e6b Mon Sep 17 00:00:00 2001 From: Red Bear OS Date: Wed, 8 Jul 2026 22:44:11 +0300 Subject: [PATCH] xhcid: cap protocol_speeds slice at max 15 (xHCI spec limit) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The PSIC field in xHCI Supported Protocol Capability is 4 bits, so its value is 0-15. Using an unbounded psic() for slicing risks OOB reads if a buggy controller reports 15 but the actual data is shorter (or absent). Cap at 15 per xHCI spec §7.2 and §4.16.1.1. This matches Linux 7.1 xhci_create_port_array() which uses kcalloc_node with the count for proper allocation. --- drivers/usb/xhcid/src/xhci/extended.rs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/usb/xhcid/src/xhci/extended.rs b/drivers/usb/xhcid/src/xhci/extended.rs index 00ab6f2f1b..e15ec2ec75 100644 --- a/drivers/usb/xhcid/src/xhci/extended.rs +++ b/drivers/usb/xhcid/src/xhci/extended.rs @@ -223,16 +223,24 @@ pub const SUPP_PROTO_CAP_PORT_SLOT_TYPE_SHIFT: u8 = 0; impl SupportedProtoCap { pub unsafe fn protocol_speeds(&self) -> &[ProtocolSpeed] { + // xHCI spec §7.2: PSIC is a 4-bit field (max 15). + // xHCI spec §4.16.1.1: PSIV may be 0-15, so max 15 ProtocolSpeed entries. + // Cap at 15 to prevent OOB reads from buggy controllers. + // Cross-referenced with Linux 7.1 drivers/usb/host/xhci-mem.c + // xhci_create_port_array() which uses kcalloc_node() with the + // bounded PSIC count. + let max_psic = (self.psic() as usize).min(15); slice::from_raw_parts( &self.protocol_speeds as *const u8 as *const _, - self.psic() as usize, + max_psic, ) } pub unsafe fn protocol_speeds_mut(&mut self) -> &mut [ProtocolSpeed] { // XXX: Variance really is annoying sometimes. + let max_psic = (self.psic() as usize).min(15); slice::from_raw_parts_mut( &self.protocol_speeds as *const u8 as *mut u8 as *mut _, - self.psic() as usize, + max_psic, ) } pub fn rev_minor(&self) -> u8 {