can: ems_usb: validate CPC message lengths

ems_usb_read_bulk_callback() walks CPC messages packed in one USB
receive buffer.

Check that each declared message fits in the URB payload. Also require the
type-specific payload to cover the fields used by the CAN, state, error and
overrun handlers.

Signed-off-by: Pengpeng Hou <pengpeng@iscas.ac.cn>
Link: https://patch.msgid.link/20260706092752.79600-1-pengpeng@iscas.ac.cn
Fixes: 702171adee ("ems_usb: Added support for EMS CPC-USB/ARM7 CAN/USB interface")
Cc: stable@vger.kernel.org
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
This commit is contained in:
Pengpeng Hou
2026-07-06 17:27:52 +08:00
committed by Marc Kleine-Budde
parent 7a0cf2b249
commit 02925f5137

View File

@@ -409,6 +409,40 @@ static void ems_usb_rx_err(struct ems_usb *dev, struct ems_cpc_msg *msg)
netif_rx(skb);
}
static bool ems_usb_rx_msg_len_valid(struct ems_cpc_msg *msg)
{
size_t len = msg->length;
size_t can_len;
switch (msg->type) {
case CPC_MSG_TYPE_CAN_STATE:
return len >= sizeof(msg->msg.can_state);
case CPC_MSG_TYPE_CAN_FRAME:
case CPC_MSG_TYPE_EXT_CAN_FRAME:
case CPC_MSG_TYPE_RTR_FRAME:
case CPC_MSG_TYPE_EXT_RTR_FRAME:
if (len < CPC_CAN_MSG_MIN_SIZE)
return false;
if (msg->type == CPC_MSG_TYPE_RTR_FRAME ||
msg->type == CPC_MSG_TYPE_EXT_RTR_FRAME)
return true;
can_len = can_cc_dlc2len(msg->msg.can_msg.length & 0xf);
return len >= CPC_CAN_MSG_MIN_SIZE + can_len;
case CPC_MSG_TYPE_CAN_FRAME_ERROR:
return len >= sizeof(msg->msg.error);
case CPC_MSG_TYPE_OVERRUN:
return len >= sizeof(msg->msg.overrun);
default:
return true;
}
}
/*
* callback for bulk IN urb
*/
@@ -451,6 +485,15 @@ static void ems_usb_read_bulk_callback(struct urb *urb)
}
msg = (struct ems_cpc_msg *)&ibuf[start];
if (msg->length >
urb->actual_length - start - CPC_MSG_HEADER_LEN) {
netdev_err(netdev, "format error\n");
break;
}
if (!ems_usb_rx_msg_len_valid(msg)) {
netdev_err(netdev, "format error\n");
break;
}
switch (msg->type) {
case CPC_MSG_TYPE_CAN_STATE: