can: peak_usb: fix a potential out-of-sync while decoding packets
authorStephane Grosjean <s.grosjean@peak-system.com>
Tue, 8 Oct 2019 08:35:44 +0000 (10:35 +0200)
committerMarc Kleine-Budde <mkl@pengutronix.de>
Mon, 4 Nov 2019 20:47:20 +0000 (21:47 +0100)
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: Stephane Grosjean <s.grosjean@peak-system.com>
Fixes: 46be265d3388 ("can: usb: PEAK-System Technik PCAN-USB specific part")
Cc: linux-stable <stable@vger.kernel.org>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
drivers/net/can/usb/peak_usb/pcan_usb.c

index 617da295b6c12647d48ee8b4e88c5a099d53e13a..5a66c9f53aae624df321fb1725a04ec775cce920 100644 (file)
@@ -100,7 +100,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;
 };
@@ -547,10 +547,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) {
@@ -632,10 +637,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) {
@@ -688,7 +696,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++;
                }
        }