]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
can: gs_usb: gs_usb_receive_bulk_callback(): check actual_length before accessing...
authorMarc Kleine-Budde <mkl@pengutronix.de>
Sat, 8 Nov 2025 09:01:02 +0000 (10:01 +0100)
committerMarc Kleine-Budde <mkl@pengutronix.de>
Sun, 16 Nov 2025 16:04:13 +0000 (17:04 +0100)
The driver expects to receive a struct gs_host_frame in
gs_usb_receive_bulk_callback().

Use struct_group to describe the header of the struct gs_host_frame and
check that we have at least received the header before accessing any
members of it.

To resubmit the URB, do not dereference the pointer chain
"dev->parent->hf_size_rx" but use "parent->hf_size_rx" instead. Since
"urb->context" contains "parent", it is always defined, while "dev" is not
defined if the URB it too short.

Fixes: d08e973a77d1 ("can: gs_usb: Added support for the GS_USB CAN devices")
Link: https://patch.msgid.link/20251114-gs_usb-fix-usb-callbacks-v1-2-a29b42eacada@pengutronix.de
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
drivers/net/can/usb/gs_usb.c

index fa9bab8c89aea00a5b606ca18d4d0264b7ffc28d..51f8d694104d972ce485ebbf64e8dce38d9758b9 100644 (file)
@@ -262,13 +262,15 @@ struct canfd_quirk {
 } __packed;
 
 struct gs_host_frame {
-       u32 echo_id;
-       __le32 can_id;
+       struct_group(header,
+               u32 echo_id;
+               __le32 can_id;
 
-       u8 can_dlc;
-       u8 channel;
-       u8 flags;
-       u8 reserved;
+               u8 can_dlc;
+               u8 channel;
+               u8 flags;
+               u8 reserved;
+       );
 
        union {
                DECLARE_FLEX_ARRAY(struct classic_can, classic_can);
@@ -576,6 +578,7 @@ static void gs_usb_receive_bulk_callback(struct urb *urb)
        int rc;
        struct net_device_stats *stats;
        struct gs_host_frame *hf = urb->transfer_buffer;
+       unsigned int minimum_length;
        struct gs_tx_context *txc;
        struct can_frame *cf;
        struct canfd_frame *cfd;
@@ -594,6 +597,15 @@ static void gs_usb_receive_bulk_callback(struct urb *urb)
                return;
        }
 
+       minimum_length = sizeof(hf->header);
+       if (urb->actual_length < minimum_length) {
+               dev_err_ratelimited(&parent->udev->dev,
+                                   "short read (actual_length=%u, minimum_length=%u)\n",
+                                   urb->actual_length, minimum_length);
+
+               goto resubmit_urb;
+       }
+
        /* device reports out of range channel id */
        if (hf->channel >= parent->channel_cnt)
                goto device_detach;
@@ -687,7 +699,7 @@ static void gs_usb_receive_bulk_callback(struct urb *urb)
 resubmit_urb:
        usb_fill_bulk_urb(urb, parent->udev,
                          parent->pipe_in,
-                         hf, dev->parent->hf_size_rx,
+                         hf, parent->hf_size_rx,
                          gs_usb_receive_bulk_callback, parent);
 
        rc = usb_submit_urb(urb, GFP_ATOMIC);