Commit f68eafeb authored by Vincent Mailhol's avatar Vincent Mailhol Committed by Marc Kleine-Budde
Browse files

can: do not copy the payload of RTR frames

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: default avatarYasushi SHOJI <yashi@spacecubics.com>
Signed-off-by: default avatarVincent Mailhol <mailhol.vincent@wanadoo.fr>
Signed-off-by: default avatarMarc Kleine-Budde <mkl@pengutronix.de>
parent 0b0ce2c6
Loading
Loading
Loading
Loading
+8 −7
Original line number Original line Diff line number Diff line
@@ -677,17 +677,18 @@ static int pch_can_rx_normal(struct net_device *ndev, u32 obj_num, int quota)
			cf->can_id = id;
			cf->can_id = id;
		}
		}


		if (id2 & PCH_ID2_DIR)
			cf->can_id |= CAN_RTR_FLAG;

		cf->len = can_cc_dlc2len((ioread32(&priv->regs->
		cf->len = can_cc_dlc2len((ioread32(&priv->regs->
						    ifregs[0].mcont)) & 0xF);
						    ifregs[0].mcont)) & 0xF);


		if (id2 & PCH_ID2_DIR) {
			cf->can_id |= CAN_RTR_FLAG;
		} else {
			for (i = 0; i < cf->len; i += 2) {
			for (i = 0; i < cf->len; i += 2) {
				data_reg = ioread16(&priv->regs->ifregs[0].data[i / 2]);
				data_reg = ioread16(&priv->regs->ifregs[0].data[i / 2]);
				cf->data[i] = data_reg;
				cf->data[i] = data_reg;
				cf->data[i + 1] = data_reg >> 8;
				cf->data[i + 1] = data_reg >> 8;
			}
			}
		}


		rcv_pkts++;
		rcv_pkts++;
		stats->rx_packets++;
		stats->rx_packets++;
+2 −1
Original line number Original line Diff line number Diff line
@@ -730,6 +730,7 @@ static void mcp251x_hw_rx(struct spi_device *spi, int buf_idx)
	}
	}
	/* Data length */
	/* Data length */
	frame->len = can_cc_dlc2len(buf[RXBDLC_OFF] & RXBDLC_LEN_MASK);
	frame->len = can_cc_dlc2len(buf[RXBDLC_OFF] & RXBDLC_LEN_MASK);
	if (!(frame->can_id & CAN_RTR_FLAG))
		memcpy(frame->data, buf + RXBDAT_OFF, frame->len);
		memcpy(frame->data, buf + RXBDAT_OFF, frame->len);


	priv->net->stats.rx_packets++;
	priv->net->stats.rx_packets++;
+4 −4
Original line number Original line Diff line number Diff line
@@ -450,11 +450,11 @@ static void mcba_usb_process_can(struct mcba_priv *priv,
		cf->can_id = (sid & 0xffe0) >> 5;
		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);
	cf->len = can_cc_dlc2len(msg->dlc & MCBA_DLC_MASK);


	if (msg->dlc & MCBA_DLC_RTR_MASK)
		cf->can_id |= CAN_RTR_FLAG;
	else
		memcpy(cf->data, msg->data, cf->len);
		memcpy(cf->data, msg->data, cf->len);


	stats->rx_packets++;
	stats->rx_packets++;