]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
USB: gadget: detect too-big endpoint 0 requests
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 9 Dec 2021 17:59:27 +0000 (18:59 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 14 Dec 2021 09:18:08 +0000 (10:18 +0100)
commit 153a2d7e3350cc89d406ba2d35be8793a64c2038 upstream.

Sometimes USB hosts can ask for buffers that are too large from endpoint
0, which should not be allowed.  If this happens for OUT requests, stall
the endpoint, but for IN requests, trim the request size to the endpoint
buffer size.

Co-developed-by: Szymon Heidrich <szymon.heidrich@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/usb/gadget/composite.c
drivers/usb/gadget/legacy/dbgp.c
drivers/usb/gadget/legacy/inode.c

index a76ed4acb57002b191ee34bc5a341176ca830d74..520c9a1b17d656fb660cfb1ff4aa64207096722f 100644 (file)
@@ -1634,6 +1634,18 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
        struct usb_function             *f = NULL;
        u8                              endp;
 
+       if (w_length > USB_COMP_EP0_BUFSIZ) {
+               if (ctrl->bRequestType == USB_DIR_OUT) {
+                       goto done;
+               } else {
+                       /* Cast away the const, we are going to overwrite on purpose. */
+                       __le16 *temp = (__le16 *)&ctrl->wLength;
+
+                       *temp = cpu_to_le16(USB_COMP_EP0_BUFSIZ);
+                       w_length = USB_COMP_EP0_BUFSIZ;
+               }
+       }
+
        /* partial re-init of the response message; the function or the
         * gadget might need to intercept e.g. a control-OUT completion
         * when we delegate to it.
index e1d566c9918ae576d55fc322f317d2992193b7f1..e567afcb2794c048044ab1a24d00a42d3db34a9f 100644 (file)
@@ -345,6 +345,19 @@ static int dbgp_setup(struct usb_gadget *gadget,
        void *data = NULL;
        u16 len = 0;
 
+       if (length > DBGP_REQ_LEN) {
+               if (ctrl->bRequestType == USB_DIR_OUT) {
+                       return err;
+               } else {
+                       /* Cast away the const, we are going to overwrite on purpose. */
+                       __le16 *temp = (__le16 *)&ctrl->wLength;
+
+                       *temp = cpu_to_le16(DBGP_REQ_LEN);
+                       length = DBGP_REQ_LEN;
+               }
+       }
+
+
        if (request == USB_REQ_GET_DESCRIPTOR) {
                switch (value>>8) {
                case USB_DT_DEVICE:
index 09ed5f02c24f4a6449364df8acae499d271fc112..848562222015d6e7bc35b829c13f26bbf9bd8cb0 100644 (file)
@@ -109,6 +109,8 @@ enum ep0_state {
 /* enough for the whole queue: most events invalidate others */
 #define        N_EVENT                 5
 
+#define RBUF_SIZE              256
+
 struct dev_data {
        spinlock_t                      lock;
        refcount_t                      count;
@@ -143,7 +145,7 @@ struct dev_data {
        struct dentry                   *dentry;
 
        /* except this scratch i/o buffer for ep0 */
-       u8                              rbuf [256];
+       u8                              rbuf[RBUF_SIZE];
 };
 
 static inline void get_dev (struct dev_data *data)
@@ -1332,6 +1334,18 @@ gadgetfs_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
        u16                             w_value = le16_to_cpu(ctrl->wValue);
        u16                             w_length = le16_to_cpu(ctrl->wLength);
 
+       if (w_length > RBUF_SIZE) {
+               if (ctrl->bRequestType == USB_DIR_OUT) {
+                       return value;
+               } else {
+                       /* Cast away the const, we are going to overwrite on purpose. */
+                       __le16 *temp = (__le16 *)&ctrl->wLength;
+
+                       *temp = cpu_to_le16(RBUF_SIZE);
+                       w_length = RBUF_SIZE;
+               }
+       }
+
        spin_lock (&dev->lock);
        dev->setup_abort = 0;
        if (dev->state == STATE_DEV_UNCONNECTED) {