diff options
Diffstat (limited to 'meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2021-39685.patch')
-rw-r--r-- | meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2021-39685.patch | 108 |
1 files changed, 108 insertions, 0 deletions
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2021-39685.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2021-39685.patch new file mode 100644 index 000000000..f94ac946b --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2021-39685.patch @@ -0,0 +1,108 @@ +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: [PATCH] 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 504c1cbc255d14..1ef7922b57b62e 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 e1d566c9918ae5..e567afcb2794c0 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 539220d7f5b620..0a4041552ed193 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) { |