* [PATCH] can: kvaser_pciefd: validate DMA packet extents
@ 2026-08-30 12:43 Pengpeng Hou
0 siblings, 0 replies; only message in thread
From: Pengpeng Hou @ 2026-08-30 12:43 UTC (permalink / raw)
To: Marc Kleine-Budde; +Cc: Pengpeng Hou, Vincent Mailhol, linux-can, linux-kernel
The RX parser reads a packet header and payload before checking the packet
size. It also compares its word index against the DMA buffer size in bytes,
allowing the loop index to pass the end of the 4 KiB buffer.
Bound the word index, require the fixed packet header, validate the
declared packet span, and prove a CAN payload fits before passing it to the
packet handler.
Fixes: 26ad340e582d ("can: kvaser_pciefd: Add driver for Kvaser PCIEcan devices")
Signed-off-by: Pengpeng Hou <pengpeng@iscas.ac.cn>
---
drivers/net/can/kvaser_pciefd/kvaser_pciefd_core.c | 20 ++++++++++++++++++--
1 file changed, 18 insertions(+), 2 deletions(-)
diff --git a/drivers/net/can/kvaser_pciefd/kvaser_pciefd_core.c b/drivers/net/can/kvaser_pciefd/kvaser_pciefd_core.c
index d8c9bfb202304..354a9e29a056e 100644
--- a/drivers/net/can/kvaser_pciefd/kvaser_pciefd_core.c
+++ b/drivers/net/can/kvaser_pciefd/kvaser_pciefd_core.c
@@ -1552,6 +1552,7 @@ static int kvaser_pciefd_read_packet(struct kvaser_pciefd *pcie, int *start_pos,
int dma_buf)
{
__le32 *buffer = pcie->dma_data[dma_buf];
+ const int buffer_words = KVASER_PCIEFD_DMA_SIZE / sizeof(*buffer);
__le64 timestamp;
struct kvaser_pciefd_rx_packet packet;
struct kvaser_pciefd_rx_packet *p = &packet;
@@ -1560,11 +1561,16 @@ static int kvaser_pciefd_read_packet(struct kvaser_pciefd *pcie, int *start_pos,
int size;
int ret = 0;
+ if (*start_pos < 0 || *start_pos >= buffer_words)
+ return -EIO;
+
size = le32_to_cpu(buffer[pos++]);
if (!size) {
*start_pos = 0;
return 0;
}
+ if (size < 5 || size > buffer_words - *start_pos)
+ return -EIO;
p->header[0] = le32_to_cpu(buffer[pos++]);
p->header[1] = le32_to_cpu(buffer[pos++]);
@@ -1577,13 +1583,22 @@ static int kvaser_pciefd_read_packet(struct kvaser_pciefd *pcie, int *start_pos,
type = FIELD_GET(KVASER_PCIEFD_PACKET_TYPE_MASK, p->header[1]);
switch (type) {
case KVASER_PCIEFD_PACK_TYPE_DATA:
+ if (!(p->header[0] & KVASER_PCIEFD_RPACKET_RTR)) {
+ u8 data_len, data_words;
+
+ data_len = can_fd_dlc2len(FIELD_GET(KVASER_PCIEFD_RPACKET_DLC_MASK,
+ p->header[1]));
+ data_words = DIV_ROUND_UP(data_len, sizeof(*buffer));
+ if (data_words > *start_pos + size - pos)
+ return -EIO;
+ }
ret = kvaser_pciefd_handle_data_packet(pcie, p, &buffer[pos]);
if (!(p->header[0] & KVASER_PCIEFD_RPACKET_RTR)) {
u8 data_len;
data_len = can_fd_dlc2len(FIELD_GET(KVASER_PCIEFD_RPACKET_DLC_MASK,
p->header[1]));
- pos += DIV_ROUND_UP(data_len, 4);
+ pos += DIV_ROUND_UP(data_len, sizeof(*buffer));
}
break;
@@ -1640,7 +1655,8 @@ static int kvaser_pciefd_read_buffer(struct kvaser_pciefd *pcie, int dma_buf)
do {
res = kvaser_pciefd_read_packet(pcie, &pos, dma_buf);
- } while (!res && pos > 0 && pos < KVASER_PCIEFD_DMA_SIZE);
+ } while (!res && pos > 0 &&
+ pos < KVASER_PCIEFD_DMA_SIZE / sizeof(__le32));
/* Report ACKs in this buffer to BQL en masse for correct periods */
for (i = 0; i < pcie->nr_channels; ++i) {
base-commit: 08dbfad3f5040f5bdb6c529da20d6d4e81fefd72
--
2.50.1
^ permalink raw reply related [flat|nested] only message in thread
only message in thread, other threads:[~2026-08-30 12:43 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-30 12:43 [PATCH] can: kvaser_pciefd: validate DMA packet extents Pengpeng Hou
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox