catc_rx_done() parses multi-packet USB transfers by iterating over the received data. For each packet, it reads a 2-byte little-endian length from the buffer, then copies that many bytes as the packet payload. The bounds check "pkt_len > urb->actual_length" is insufficient: 1. It does not account for the 2-byte header offset, so the memcpy can read 2 bytes beyond the received data. 2. For subsequent packets in the same URB, pkt_start advances through the buffer but the check still compares against the total urb->actual_length rather than the remaining bytes, allowing reads well past the end. Fix this by calculating the remaining bytes from the current pkt_start position and checking both that enough bytes exist to read the header and that the packet length plus header fits within the remaining data. A malicious USB device can craft transfers that trigger the out-of-bounds heap read. Fixes: 1da177e4c3f41 ("Linux-2.6.12-rc2") Cc: stable@vger.kernel.org Signed-off-by: Aamir Ahmed Assisted-by: Claude (Anthropic) --- drivers/net/usb/catc.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/net/usb/catc.c b/drivers/net/usb/catc.c index 96e82f94edcf8..e4f8b9a0caf19 100644 --- a/drivers/net/usb/catc.c +++ b/drivers/net/usb/catc.c @@ -234,8 +234,16 @@ static void catc_rx_done(struct urb *urb) do { if(!catc->is_f5u011) { + int remaining = urb->actual_length - + (pkt_start - (u8 *)urb->transfer_buffer); + + if (remaining < pkt_offset) { + catc->netdev->stats.rx_length_errors++; + catc->netdev->stats.rx_errors++; + break; + } pkt_len = le16_to_cpup((__le16*)pkt_start); - if (pkt_len > urb->actual_length) { + if (pkt_len + pkt_offset > remaining) { catc->netdev->stats.rx_length_errors++; catc->netdev->stats.rx_errors++; break; -- 2.43.0