8c3abf9a1d
[ci:skip-build] Already built on CI in MR
110 lines
3.5 KiB
Diff
110 lines
3.5 KiB
Diff
From 36dfdf11af49d3c009c711fb16f5c6e7a274505d Mon Sep 17 00:00:00 2001
|
|
From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
|
Date: Thu, 9 Dec 2021 18:59:27 +0100
|
|
Subject: USB: gadget: detect too-big endpoint 0 requests
|
|
|
|
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 | 12 ++++++++++++
|
|
drivers/usb/gadget/legacy/dbgp.c | 13 +++++++++++++
|
|
drivers/usb/gadget/legacy/inode.c | 16 +++++++++++++++-
|
|
3 files changed, 40 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
|
|
index 504c1cbc255d1..1ef7922b57b62 100644
|
|
--- a/drivers/usb/gadget/composite.c
|
|
+++ b/drivers/usb/gadget/composite.c
|
|
@@ -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.
|
|
diff --git a/drivers/usb/gadget/legacy/dbgp.c b/drivers/usb/gadget/legacy/dbgp.c
|
|
index e1d566c9918ae..e567afcb2794c 100644
|
|
--- a/drivers/usb/gadget/legacy/dbgp.c
|
|
+++ b/drivers/usb/gadget/legacy/dbgp.c
|
|
@@ -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:
|
|
diff --git a/drivers/usb/gadget/legacy/inode.c b/drivers/usb/gadget/legacy/inode.c
|
|
index 539220d7f5b62..0a4041552ed19 100644
|
|
--- a/drivers/usb/gadget/legacy/inode.c
|
|
+++ b/drivers/usb/gadget/legacy/inode.c
|
|
@@ -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;
|
|
@@ -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)
|
|
@@ -1334,6 +1336,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) {
|
|
--
|
|
cgit 1.2.3-1.el7
|