[PATCH net] can: peak_usb: accept short uCAN end-of-list records
From: Liu Changjie
Date: Sun Oct 18 2026 - 12:46:04 EST
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. These transfers
cause repeated receive-buffer dumps while the interface is up.
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.
Fixes: 93fcab2c6968 ("can: peak_usb: validate uCAN receive record lengths")
Assisted-by: LLM
Signed-off-by: Liu Changjie <liucj1228@xxxxxxxxxxx>
---
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 0d46f4c..39f0740 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);