can: do not copy the payload of RTR frames
authorVincent Mailhol <mailhol.vincent@wanadoo.fr>
Tue, 7 Dec 2021 12:15:29 +0000 (21:15 +0900)
committerMarc Kleine-Budde <mkl@pengutronix.de>
Wed, 5 Jan 2022 11:09:05 +0000 (12:09 +0100)
The actual payload length of the CAN Remote Transmission Request (RTR)
frames is always 0, i.e. no payload is transmitted on the wire.
However, those RTR frames still use the DLC to indicate the length of
the requested frame.

For this reason, it is incorrect to copy the payload of RTR frames
(the payload buffer would only contain garbage data). This patch
encapsulates the payload copy in a check toward the RTR flag.

Link: https://lore.kernel.org/all/20211207121531.42941-4-mailhol.vincent@wanadoo.fr
Cc: Yasushi SHOJI <yashi@spacecubics.com>
Tested-by: Yasushi SHOJI <yashi@spacecubics.com>
Signed-off-by: Vincent Mailhol <mailhol.vincent@wanadoo.fr>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
drivers/net/can/pch_can.c
drivers/net/can/spi/mcp251x.c
drivers/net/can/usb/mcba_usb.c

index 6b45840..4bf9bfc 100644 (file)
@@ -677,16 +677,17 @@ static int pch_can_rx_normal(struct net_device *ndev, u32 obj_num, int quota)
                        cf->can_id = id;
                }
 
-               if (id2 & PCH_ID2_DIR)
-                       cf->can_id |= CAN_RTR_FLAG;
-
                cf->len = can_cc_dlc2len((ioread32(&priv->regs->
                                                    ifregs[0].mcont)) & 0xF);
 
-               for (i = 0; i < cf->len; i += 2) {
-                       data_reg = ioread16(&priv->regs->ifregs[0].data[i / 2]);
-                       cf->data[i] = data_reg;
-                       cf->data[i + 1] = data_reg >> 8;
+               if (id2 & PCH_ID2_DIR) {
+                       cf->can_id |= CAN_RTR_FLAG;
+               } else {
+                       for (i = 0; i < cf->len; i += 2) {
+                               data_reg = ioread16(&priv->regs->ifregs[0].data[i / 2]);
+                               cf->data[i] = data_reg;
+                               cf->data[i + 1] = data_reg >> 8;
+                       }
                }
 
                rcv_pkts++;
index 0cec808..2fa1e85 100644 (file)
@@ -730,7 +730,8 @@ static void mcp251x_hw_rx(struct spi_device *spi, int buf_idx)
        }
        /* Data length */
        frame->len = can_cc_dlc2len(buf[RXBDLC_OFF] & RXBDLC_LEN_MASK);
-       memcpy(frame->data, buf + RXBDAT_OFF, frame->len);
+       if (!(frame->can_id & CAN_RTR_FLAG))
+               memcpy(frame->data, buf + RXBDAT_OFF, frame->len);
 
        priv->net->stats.rx_packets++;
        priv->net->stats.rx_bytes += frame->len;
index a1a154c..162d2e1 100644 (file)
@@ -450,12 +450,12 @@ static void mcba_usb_process_can(struct mcba_priv *priv,
                cf->can_id = (sid & 0xffe0) >> 5;
        }
 
-       if (msg->dlc & MCBA_DLC_RTR_MASK)
-               cf->can_id |= CAN_RTR_FLAG;
-
        cf->len = can_cc_dlc2len(msg->dlc & MCBA_DLC_MASK);
 
-       memcpy(cf->data, msg->data, cf->len);
+       if (msg->dlc & MCBA_DLC_RTR_MASK)
+               cf->can_id |= CAN_RTR_FLAG;
+       else
+               memcpy(cf->data, msg->data, cf->len);
 
        stats->rx_packets++;
        stats->rx_bytes += cf->len;