Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d9510ea1 authored by Stephane Grosjean's avatar Stephane Grosjean Committed by Greg Kroah-Hartman
Browse files

can: peak_usb: fix a potential out-of-sync while decoding packets



commit de280f403f2996679e2607384980703710576fed upstream.

When decoding a buffer received from PCAN-USB, the first timestamp read in
a packet is a 16-bit coded time base, and the next ones are an 8-bit
offset to this base, regardless of the type of packet read.

This patch corrects a potential loss of synchronization by using a
timestamp index read from the buffer, rather than an index of received
data packets, to determine on the sizeof the timestamp to be read from the
packet being decoded.

Signed-off-by: default avatarStephane Grosjean <s.grosjean@peak-system.com>
Fixes: 46be265d ("can: usb: PEAK-System Technik PCAN-USB specific part")
Cc: linux-stable <stable@vger.kernel.org>
Signed-off-by: default avatarMarc Kleine-Budde <mkl@pengutronix.de>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 7a5f2a35
Loading
Loading
Loading
Loading
+12 −5
Original line number Diff line number Diff line
@@ -108,7 +108,7 @@ struct pcan_usb_msg_context {
	u8 *end;
	u8 rec_cnt;
	u8 rec_idx;
	u8 rec_data_idx;
	u8 rec_ts_idx;
	struct net_device *netdev;
	struct pcan_usb *pdev;
};
@@ -552,10 +552,15 @@ static int pcan_usb_decode_status(struct pcan_usb_msg_context *mc,
	mc->ptr += PCAN_USB_CMD_ARGS;

	if (status_len & PCAN_USB_STATUSLEN_TIMESTAMP) {
		int err = pcan_usb_decode_ts(mc, !mc->rec_idx);
		int err = pcan_usb_decode_ts(mc, !mc->rec_ts_idx);

		if (err)
			return err;

		/* Next packet in the buffer will have a timestamp on a single
		 * byte
		 */
		mc->rec_ts_idx++;
	}

	switch (f) {
@@ -638,10 +643,13 @@ static int pcan_usb_decode_data(struct pcan_usb_msg_context *mc, u8 status_len)

	cf->can_dlc = get_can_dlc(rec_len);

	/* first data packet timestamp is a word */
	if (pcan_usb_decode_ts(mc, !mc->rec_data_idx))
	/* Only first packet timestamp is a word */
	if (pcan_usb_decode_ts(mc, !mc->rec_ts_idx))
		goto decode_failed;

	/* Next packet in the buffer will have a timestamp on a single byte */
	mc->rec_ts_idx++;

	/* read data */
	memset(cf->data, 0x0, sizeof(cf->data));
	if (status_len & PCAN_USB_STATUSLEN_RTR) {
@@ -695,7 +703,6 @@ static int pcan_usb_decode_msg(struct peak_usb_device *dev, u8 *ibuf, u32 lbuf)
		/* handle normal can frames here */
		} else {
			err = pcan_usb_decode_data(&mc, sl);
			mc.rec_data_idx++;
		}
	}