From 2d4c272e816a5b784f1fc7899256f8826df34edb Mon Sep 17 00:00:00 2001 From: Liu Changjie Date: Mon, 19 Oct 2026 00:46:34 +0800 Subject: [PATCH] can: peak_usb: pcan_usb_fd_decode_buf(): accept short uCAN end-of-list records MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A PCAN-USB FD v2 running firmware 3.2.0 sends a 16-byte status record followed by a four-byte zero-size end marker. Since commit 93fcab2c6968 ("can: peak_usb: validate uCAN receive record lengths") these transfers cause repeated receive-buffer dumps while the interface is up. This has been observed on Linux 7.2.11-arch1-1 with matching kernel headers: - Classic CAN, 500 kbit/s: 25 decoder errors in 5 s before the fix; none in 15 s after. - CAN FD, 500 kbit/s nominal and 2 Mbit/s data: 26 decoder errors in 5 s before the fix; none in 60 s after. - Three additional down/up cycles: no decoder errors. pcan_usb_fd_decode_buf() requires a complete 12-byte struct pucan_msg before checking the size field, so it rejects the end marker with -EBADMSG. Check that the size field is present before testing for an end marker. Require the full header for nonzero-size records and keep the remaining record and payload length checks. This patch was created with LLM assistance. Fixes: 93fcab2c6968 ("can: peak_usb: validate uCAN receive record lengths") Signed-off-by: Liu Changjie Reviewed-by: Stéphane Grosjean Link: https://patch.msgid.link/CH5PR19MB997156AB3BE253C3BE445223B0AC992@CH5PR19MB997156.namprd19.prod.outlook.com Cc: stable@vger.kernel.org [mkl: copy additional info to commit message] [mkl: convert Assisted-by: tag to prose] Signed-off-by: Marc Kleine-Budde --- Built and tested the original and patched peak_usb modules on Arch Linux 7.2.11-arch1-1 with matching kernel headers. - Classic CAN, 500 kbit/s: 25 decoder errors in 5 s before the fix; none in 15 s after. - CAN FD, 500 kbit/s nominal and 2 Mbit/s data: 26 decoder errors in 5 s before the fix; none in 60 s after. - Three additional down/up cycles: no decoder errors. USB captures during the patched tests contained 406 packets with short end markers. Neither receive-buffer dump recurred. The CAN bus was disconnected; external TX/RX was not tested. One startup "can_change_state: oops, state did not change" message and an RX dropped count reaching 2 were observed during the patched tests. Their causes remain undetermined. --- drivers/net/can/usb/peak_usb/pcan_usb_fd.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/net/can/usb/peak_usb/pcan_usb_fd.c b/drivers/net/can/usb/peak_usb/pcan_usb_fd.c index 0d46f4ce5dca..39f0740421c3 100644 --- a/drivers/net/can/usb/peak_usb/pcan_usb_fd.c +++ b/drivers/net/can/usb/peak_usb/pcan_usb_fd.c @@ -755,7 +755,7 @@ static int pcan_usb_fd_decode_buf(struct peak_usb_device *dev, struct urb *urb) u16 rx_msg_type, rx_msg_size; size_t rx_msg_min_size; - if (msg_end - msg_ptr < sizeof(*rx_msg)) { + if (msg_end - msg_ptr < sizeof(rx_msg->size)) { err = -EBADMSG; break; } @@ -766,6 +766,11 @@ static int pcan_usb_fd_decode_buf(struct peak_usb_device *dev, struct urb *urb) break; } + if (msg_end - msg_ptr < sizeof(*rx_msg)) { + err = -EBADMSG; + break; + } + rx_msg_size = le16_to_cpu(rx_msg->size); rx_msg_type = le16_to_cpu(rx_msg->type);