* [PATCH] can: peak_usb: validate uCAN receive record lengths
@ 2026-07-06 9:28 Pengpeng Hou
2026-07-06 9:41 ` sashiko-bot
0 siblings, 1 reply; 2+ messages in thread
From: Pengpeng Hou @ 2026-07-06 9:28 UTC (permalink / raw)
To: Marc Kleine-Budde
Cc: Pengpeng Hou, Vincent Mailhol, Stéphane Grosjean, Kees Cook,
linux-can, linux-kernel
pcan_usb_fd_decode_buf() walks uCAN records packed in one USB
receive buffer.
Require each record to contain the fixed header for its type, and verify
CAN payload bytes before copying them into the skb.
Signed-off-by: Pengpeng Hou <pengpeng@iscas.ac.cn>
---
drivers/net/can/usb/peak_usb/pcan_usb_fd.c | 40 +++++++++++++++++++++-
1 file changed, 39 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 eb4f5884ad73..45ae4611ae4c 100644
--- a/drivers/net/can/usb/peak_usb/pcan_usb_fd.c
+++ b/drivers/net/can/usb/peak_usb/pcan_usb_fd.c
@@ -566,6 +566,13 @@ static int pcan_usb_fd_decode_canmsg(struct pcan_usb_fd_if *usb_if,
dev->can.ctrlmode);
}
+ if (!(rx_msg_flags & PUCAN_MSG_RTR) &&
+ le16_to_cpu(rx_msg->size) - offsetof(struct pucan_rx_msg, d) <
+ cfd->len) {
+ kfree_skb(skb);
+ return -EBADMSG;
+ }
+
cfd->can_id = le32_to_cpu(rm->can_id);
if (rx_msg_flags & PUCAN_MSG_EXT_ID)
@@ -714,6 +721,24 @@ static void pcan_usb_fd_decode_ts(struct pcan_usb_fd_if *usb_if,
peak_usb_set_ts_now(&usb_if->time_ref, le32_to_cpu(ts->ts_low));
}
+static size_t pcan_usb_fd_rx_msg_min_size(u16 rx_msg_type)
+{
+ switch (rx_msg_type) {
+ case PUCAN_MSG_CAN_RX:
+ return offsetof(struct pucan_rx_msg, d);
+ case PCAN_UFD_MSG_CALIBRATION:
+ return sizeof(struct pcan_ufd_ts_msg);
+ case PUCAN_MSG_ERROR:
+ return sizeof(struct pucan_error_msg);
+ case PUCAN_MSG_STATUS:
+ return sizeof(struct pucan_status_msg);
+ case PCAN_UFD_MSG_OVERRUN:
+ return sizeof(struct pcan_ufd_ovr_msg);
+ default:
+ return sizeof(struct pucan_msg);
+ }
+}
+
/* callback for bulk IN urb */
static int pcan_usb_fd_decode_buf(struct peak_usb_device *dev, struct urb *urb)
{
@@ -728,6 +753,12 @@ static int pcan_usb_fd_decode_buf(struct peak_usb_device *dev, struct urb *urb)
msg_end = urb->transfer_buffer + urb->actual_length;
for (; msg_ptr < msg_end;) {
u16 rx_msg_type, rx_msg_size;
+ size_t rx_msg_min_size;
+
+ if (msg_end - msg_ptr < sizeof(*rx_msg)) {
+ err = -EBADMSG;
+ break;
+ }
rx_msg = (struct pucan_msg *)msg_ptr;
if (!rx_msg->size) {
@@ -739,13 +770,20 @@ static int pcan_usb_fd_decode_buf(struct peak_usb_device *dev, struct urb *urb)
rx_msg_type = le16_to_cpu(rx_msg->type);
/* check if the record goes out of current packet */
- if (msg_ptr + rx_msg_size > msg_end) {
+ if (rx_msg_size > msg_end - msg_ptr) {
netdev_err(netdev,
"got frag rec: should inc usb rx buf sze\n");
err = -EBADMSG;
break;
}
+ rx_msg_min_size = pcan_usb_fd_rx_msg_min_size(rx_msg_type);
+ if (rx_msg_size < rx_msg_min_size) {
+ netdev_err(netdev, "got short rec\n");
+ err = -EBADMSG;
+ break;
+ }
+
switch (rx_msg_type) {
case PUCAN_MSG_CAN_RX:
err = pcan_usb_fd_decode_canmsg(usb_if, rx_msg);
--
2.43.0
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: [PATCH] can: peak_usb: validate uCAN receive record lengths
2026-07-06 9:28 [PATCH] can: peak_usb: validate uCAN receive record lengths Pengpeng Hou
@ 2026-07-06 9:41 ` sashiko-bot
0 siblings, 0 replies; 2+ messages in thread
From: sashiko-bot @ 2026-07-06 9:41 UTC (permalink / raw)
To: Pengpeng Hou
Cc: Oliver Hartkopp, Vincent Mailhol, Oleksij Rempel, linux-can,
Marc Kleine-Budde
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
Pre-existing issues:
- [High] The decoders blindly trust the device-provided channel index to retrieve the device pointer, leading to a NULL pointer dereference if the channel is within array bounds but uninitialized.
--
commit 35cea41238e6f7cd42684d301dadde24023e663a
Author: Pengpeng Hou <pengpeng@iscas.ac.cn>
can: peak_usb: validate uCAN receive record lengths
pcan_usb_fd_decode_buf() walks uCAN records packed in one USB
receive buffer. Require each record to contain the fixed header for its
type, and verify CAN payload bytes before copying them into the skb.
> 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 eb4f5884ad735..45ae4611ae4c3 100644
> --- a/drivers/net/can/usb/peak_usb/pcan_usb_fd.c
> +++ b/drivers/net/can/usb/peak_usb/pcan_usb_fd.c
> @@ -566,6 +566,13 @@ static int pcan_usb_fd_decode_canmsg(struct pcan_usb_fd_if *usb_if,
> dev->can.ctrlmode);
> }
>
[Severity: High]
This is a pre-existing issue, but I noticed a potential NULL pointer
dereference just above this hunk in pcan_usb_fd_decode_canmsg().
The function currently checks the channel index against the array size:
if (pucan_msg_get_channel(rm) >= ARRAY_SIZE(usb_if->dev))
return -ENOMEM;
dev = usb_if->dev[pucan_msg_get_channel(rm)];
netdev = dev->netdev;
Does this bounds check properly validate against the number of initialized
channels? If the adapter only has 1 channel (like the PCAN-USB FD), channel 0
is initialized but channel 1 is NULL. Since ARRAY_SIZE(usb_if->dev) is 2, a
malicious USB device could send a message with a channel index of 1, which
passes the bounds check but results in a crash when dev->netdev is accessed.
It appears this same pattern exists in pcan_usb_fd_decode_status(),
pcan_usb_fd_decode_error(), and pcan_usb_fd_decode_overrun() in this file.
Should we verify if dev is NULL before dereferencing it in these decoders?
> + if (!(rx_msg_flags & PUCAN_MSG_RTR) &&
> + le16_to_cpu(rx_msg->size) - offsetof(struct pucan_rx_msg, d) <
> + cfd->len) {
> + kfree_skb(skb);
> + return -EBADMSG;
> + }
> +
> cfd->can_id = le32_to_cpu(rm->can_id);
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260706092836.79754-1-pengpeng@iscas.ac.cn?part=1
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-07-06 9:41 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-06 9:28 [PATCH] can: peak_usb: validate uCAN receive record lengths Pengpeng Hou
2026-07-06 9:41 ` sashiko-bot
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.