Skip to content

Commit 153a2d7

Browse files
committed
USB: gadget: detect too-big endpoint 0 requests
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 <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 7faac19 commit 153a2d7

File tree

3 files changed

+40
-1
lines changed

3 files changed

+40
-1
lines changed

drivers/usb/gadget/composite.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1679,6 +1679,18 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
16791679
struct usb_function *f = NULL;
16801680
u8 endp;
16811681

1682+
if (w_length > USB_COMP_EP0_BUFSIZ) {
1683+
if (ctrl->bRequestType == USB_DIR_OUT) {
1684+
goto done;
1685+
} else {
1686+
/* Cast away the const, we are going to overwrite on purpose. */
1687+
__le16 *temp = (__le16 *)&ctrl->wLength;
1688+
1689+
*temp = cpu_to_le16(USB_COMP_EP0_BUFSIZ);
1690+
w_length = USB_COMP_EP0_BUFSIZ;
1691+
}
1692+
}
1693+
16821694
/* partial re-init of the response message; the function or the
16831695
* gadget might need to intercept e.g. a control-OUT completion
16841696
* when we delegate to it.

drivers/usb/gadget/legacy/dbgp.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,19 @@ static int dbgp_setup(struct usb_gadget *gadget,
345345
void *data = NULL;
346346
u16 len = 0;
347347

348+
if (length > DBGP_REQ_LEN) {
349+
if (ctrl->bRequestType == USB_DIR_OUT) {
350+
return err;
351+
} else {
352+
/* Cast away the const, we are going to overwrite on purpose. */
353+
__le16 *temp = (__le16 *)&ctrl->wLength;
354+
355+
*temp = cpu_to_le16(DBGP_REQ_LEN);
356+
length = DBGP_REQ_LEN;
357+
}
358+
}
359+
360+
348361
if (request == USB_REQ_GET_DESCRIPTOR) {
349362
switch (value>>8) {
350363
case USB_DT_DEVICE:

drivers/usb/gadget/legacy/inode.c

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,8 @@ enum ep0_state {
110110
/* enough for the whole queue: most events invalidate others */
111111
#define N_EVENT 5
112112

113+
#define RBUF_SIZE 256
114+
113115
struct dev_data {
114116
spinlock_t lock;
115117
refcount_t count;
@@ -144,7 +146,7 @@ struct dev_data {
144146
struct dentry *dentry;
145147

146148
/* except this scratch i/o buffer for ep0 */
147-
u8 rbuf [256];
149+
u8 rbuf[RBUF_SIZE];
148150
};
149151

150152
static inline void get_dev (struct dev_data *data)
@@ -1331,6 +1333,18 @@ gadgetfs_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
13311333
u16 w_value = le16_to_cpu(ctrl->wValue);
13321334
u16 w_length = le16_to_cpu(ctrl->wLength);
13331335

1336+
if (w_length > RBUF_SIZE) {
1337+
if (ctrl->bRequestType == USB_DIR_OUT) {
1338+
return value;
1339+
} else {
1340+
/* Cast away the const, we are going to overwrite on purpose. */
1341+
__le16 *temp = (__le16 *)&ctrl->wLength;
1342+
1343+
*temp = cpu_to_le16(RBUF_SIZE);
1344+
w_length = RBUF_SIZE;
1345+
}
1346+
}
1347+
13341348
spin_lock (&dev->lock);
13351349
dev->setup_abort = 0;
13361350
if (dev->state == STATE_DEV_UNCONNECTED) {

0 commit comments

Comments
 (0)