Skip to content

Commit 6b8cf54

Browse files
Jiale Yaogregkh
authored andcommitted
USB: serial: option: fix slab OOB read in interrupt URB callback
commit 885d802 upstream. The interrupt URB buffer is allocated in setup_port_interrupt_in() based on the endpoint's wMaxPacketSize: buffer_size = usb_endpoint_maxp(epd); port->interrupt_in_buffer = kmalloc(buffer_size, GFP_KERNEL); When a USB device declares wMaxPacketSize = 8 on its interrupt IN endpoint, the buffer is allocated from kmalloc-8 cache (exactly 8 bytes). If the device sends a short packet (actual_length < wMaxPacketSize), the URB completes with status == 0 and the callback proceeds to read: data[sizeof(struct usb_ctrlrequest)] which evaluates to data[8], accessing 1 byte beyond the allocated 8-byte buffer. This results in a slab out-of-bounds read. Fix this by adding the missing bounds check: first verify that the actual length is large enough to contain the struct usb_ctrlrequest header before accessing req_pkt->bRequestType and req_pkt->bRequest, and then verify that there is an additional byte for the modem signal state before reading data[sizeof(struct usb_ctrlrequest)] inside the conditional. Use sizeof(*req_pkt) instead of sizeof(struct usb_ctrlrequest) for consistency. Assisted-by: Claude:deepseek-v4-pro Signed-off-by: Jiale Yao <yaojiale02@163.com> Fixes: 58cfe91 ("[PATCH] USB: add Option Card driver") Cc: stable@vger.kernel.org # v2.6.12 [ johan: use dev_err(); split signals declaration and initialisation ] Signed-off-by: Johan Hovold <johan@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 3f06f3f commit 6b8cf54

1 file changed

Lines changed: 17 additions & 3 deletions

File tree

drivers/usb/serial/option.c

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2691,12 +2691,26 @@ static void option_instat_callback(struct urb *urb)
26912691
dev_dbg(dev, "%s: NULL req_pkt\n", __func__);
26922692
return;
26932693
}
2694+
2695+
if (urb->actual_length < sizeof(*req_pkt)) {
2696+
dev_err(dev, "%s: short packet: %u bytes\n", __func__,
2697+
urb->actual_length);
2698+
return;
2699+
}
2700+
26942701
if ((req_pkt->bRequestType == 0xA1) &&
26952702
(req_pkt->bRequest == 0x20)) {
2703+
unsigned char signals;
26962704
int old_dcd_state;
2697-
unsigned char signals = *((unsigned char *)
2698-
urb->transfer_buffer +
2699-
sizeof(struct usb_ctrlrequest));
2705+
2706+
if (urb->actual_length < sizeof(*req_pkt) + 1) {
2707+
dev_err(dev, "%s: short interrupt transfer: %u bytes\n",
2708+
__func__, urb->actual_length);
2709+
return;
2710+
}
2711+
2712+
signals = *((unsigned char *)urb->transfer_buffer +
2713+
sizeof(*req_pkt));
27002714

27012715
dev_dbg(dev, "%s: signal x%x\n", __func__, signals);
27022716

0 commit comments

Comments
 (0)