Skip to content

Commit

Permalink
USB: gadget: detect too-big endpoint 0 requests
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
gregkh committed Dec 12, 2021
1 parent 7faac19 commit 153a2d7
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 1 deletion.
12 changes: 12 additions & 0 deletions drivers/usb/gadget/composite.c
Original file line number Diff line number Diff line change
Expand Up @@ -1679,6 +1679,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.
Expand Down
13 changes: 13 additions & 0 deletions drivers/usb/gadget/legacy/dbgp.c
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
16 changes: 15 additions & 1 deletion drivers/usb/gadget/legacy/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,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;
Expand Down Expand Up @@ -144,7 +146,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)
Expand Down Expand Up @@ -1331,6 +1333,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) {
Expand Down

0 comments on commit 153a2d7

Please sign in to comment.