From fe3f70d1adfaa0fb01d1ae1794c3c0fb4cb93ffc Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 14 Sep 2020 14:18:08 +0200 Subject: [PATCH] 4.4-stable patches added patches: iio-accel-mma8452-fix-timestamp-alignment-and-prevent-data-leak.patch staging-wlan-ng-fix-out-of-bounds-read-in-prism2sta_probe_usb.patch usb-core-add-helpers-to-retrieve-endpoints.patch --- ...tamp-alignment-and-prevent-data-leak.patch | 67 +++++++ queue-4.4/series | 3 + ...f-bounds-read-in-prism2sta_probe_usb.patch | 84 +++++++++ ...re-add-helpers-to-retrieve-endpoints.patch | 166 ++++++++++++++++++ 4 files changed, 320 insertions(+) create mode 100644 queue-4.4/iio-accel-mma8452-fix-timestamp-alignment-and-prevent-data-leak.patch create mode 100644 queue-4.4/staging-wlan-ng-fix-out-of-bounds-read-in-prism2sta_probe_usb.patch create mode 100644 queue-4.4/usb-core-add-helpers-to-retrieve-endpoints.patch diff --git a/queue-4.4/iio-accel-mma8452-fix-timestamp-alignment-and-prevent-data-leak.patch b/queue-4.4/iio-accel-mma8452-fix-timestamp-alignment-and-prevent-data-leak.patch new file mode 100644 index 00000000000..614805f8f69 --- /dev/null +++ b/queue-4.4/iio-accel-mma8452-fix-timestamp-alignment-and-prevent-data-leak.patch @@ -0,0 +1,67 @@ +From 89226a296d816727405d3fea684ef69e7d388bd8 Mon Sep 17 00:00:00 2001 +From: Jonathan Cameron +Date: Wed, 22 Jul 2020 16:50:38 +0100 +Subject: iio:accel:mma8452: Fix timestamp alignment and prevent data leak. + +From: Jonathan Cameron + +commit 89226a296d816727405d3fea684ef69e7d388bd8 upstream. + +One of a class of bugs pointed out by Lars in a recent review. +iio_push_to_buffers_with_timestamp assumes the buffer used is aligned +to the size of the timestamp (8 bytes). This is not guaranteed in +this driver which uses a 16 byte u8 array on the stack. As Lars also noted +this anti pattern can involve a leak of data to userspace and that +indeed can happen here. We close both issues by moving to +a suitable structure in the iio_priv() data with alignment +ensured by use of an explicit c structure. This data is allocated +with kzalloc so no data can leak appart from previous readings. + +The additional forcing of the 8 byte alignment of the timestamp +is not strictly necessary but makes the code less fragile by +making this explicit. + +Fixes: c7eeea93ac60 ("iio: Add Freescale MMA8452Q 3-axis accelerometer driver") +Reported-by: Lars-Peter Clausen +Cc: Peter Meerwald +Signed-off-by: Jonathan Cameron +Reviewed-by: Andy Shevchenko +Cc: +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/iio/accel/mma8452.c | 11 ++++++++--- + 1 file changed, 8 insertions(+), 3 deletions(-) + +--- a/drivers/iio/accel/mma8452.c ++++ b/drivers/iio/accel/mma8452.c +@@ -96,6 +96,12 @@ struct mma8452_data { + u8 ctrl_reg1; + u8 data_cfg; + const struct mma_chip_info *chip_info; ++ ++ /* Ensure correct alignment of time stamp when present */ ++ struct { ++ __be16 channels[3]; ++ s64 ts __aligned(8); ++ } buffer; + }; + + /** +@@ -700,14 +706,13 @@ static irqreturn_t mma8452_trigger_handl + struct iio_poll_func *pf = p; + struct iio_dev *indio_dev = pf->indio_dev; + struct mma8452_data *data = iio_priv(indio_dev); +- u8 buffer[16]; /* 3 16-bit channels + padding + ts */ + int ret; + +- ret = mma8452_read(data, (__be16 *)buffer); ++ ret = mma8452_read(data, data->buffer.channels); + if (ret < 0) + goto done; + +- iio_push_to_buffers_with_timestamp(indio_dev, buffer, ++ iio_push_to_buffers_with_timestamp(indio_dev, &data->buffer, + iio_get_time_ns()); + + done: diff --git a/queue-4.4/series b/queue-4.4/series index 8cf569f44eb..731229f8393 100644 --- a/queue-4.4/series +++ b/queue-4.4/series @@ -11,3 +11,6 @@ gcov-disable-gcov-build-with-gcc-10.patch iio-adc-mcp3422-fix-locking-scope.patch iio-light-ltr501-fix-timestamp-alignment-issue.patch iio-accel-bmc150-accel-fix-timestamp-alignment-and-prevent-data-leak.patch +iio-accel-mma8452-fix-timestamp-alignment-and-prevent-data-leak.patch +usb-core-add-helpers-to-retrieve-endpoints.patch +staging-wlan-ng-fix-out-of-bounds-read-in-prism2sta_probe_usb.patch diff --git a/queue-4.4/staging-wlan-ng-fix-out-of-bounds-read-in-prism2sta_probe_usb.patch b/queue-4.4/staging-wlan-ng-fix-out-of-bounds-read-in-prism2sta_probe_usb.patch new file mode 100644 index 00000000000..17ed3b4c89a --- /dev/null +++ b/queue-4.4/staging-wlan-ng-fix-out-of-bounds-read-in-prism2sta_probe_usb.patch @@ -0,0 +1,84 @@ +From fea22e159d51c766ba70473f473a0ec914cc7e92 Mon Sep 17 00:00:00 2001 +From: Rustam Kovhaev +Date: Tue, 4 Aug 2020 07:56:14 -0700 +Subject: staging: wlan-ng: fix out of bounds read in prism2sta_probe_usb() + +From: Rustam Kovhaev + +commit fea22e159d51c766ba70473f473a0ec914cc7e92 upstream. + +let's use usb_find_common_endpoints() to discover endpoints, it does all +necessary checks for type and xfer direction + +remove memset() in hfa384x_create(), because we now assign endpoints in +prism2sta_probe_usb() and because create_wlan() uses kzalloc() to +allocate hfa384x struct before calling hfa384x_create() + +Fixes: faaff9765664 ("staging: wlan-ng: properly check endpoint types") +Reported-and-tested-by: syzbot+22794221ab96b0bab53a@syzkaller.appspotmail.com +Link: https://syzkaller.appspot.com/bug?extid=22794221ab96b0bab53a +Signed-off-by: Rustam Kovhaev +Cc: stable +Link: https://lore.kernel.org/r/20200804145614.104320-1-rkovhaev@gmail.com +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/staging/wlan-ng/hfa384x_usb.c | 5 ----- + drivers/staging/wlan-ng/prism2usb.c | 19 ++++++------------- + 2 files changed, 6 insertions(+), 18 deletions(-) + +--- a/drivers/staging/wlan-ng/hfa384x_usb.c ++++ b/drivers/staging/wlan-ng/hfa384x_usb.c +@@ -530,13 +530,8 @@ static void hfa384x_usb_defer(struct wor + ----------------------------------------------------------------*/ + void hfa384x_create(hfa384x_t *hw, struct usb_device *usb) + { +- memset(hw, 0, sizeof(hfa384x_t)); + hw->usb = usb; + +- /* set up the endpoints */ +- hw->endp_in = usb_rcvbulkpipe(usb, 1); +- hw->endp_out = usb_sndbulkpipe(usb, 2); +- + /* Set up the waitq */ + init_waitqueue_head(&hw->cmdq); + +--- a/drivers/staging/wlan-ng/prism2usb.c ++++ b/drivers/staging/wlan-ng/prism2usb.c +@@ -60,23 +60,14 @@ static int prism2sta_probe_usb(struct us + const struct usb_device_id *id) + { + struct usb_device *dev; +- const struct usb_endpoint_descriptor *epd; +- const struct usb_host_interface *iface_desc = interface->cur_altsetting; ++ struct usb_endpoint_descriptor *bulk_in, *bulk_out; ++ struct usb_host_interface *iface_desc = interface->cur_altsetting; + wlandevice_t *wlandev = NULL; + hfa384x_t *hw = NULL; + int result = 0; + +- if (iface_desc->desc.bNumEndpoints != 2) { +- result = -ENODEV; +- goto failed; +- } +- +- result = -EINVAL; +- epd = &iface_desc->endpoint[1].desc; +- if (!usb_endpoint_is_bulk_in(epd)) +- goto failed; +- epd = &iface_desc->endpoint[2].desc; +- if (!usb_endpoint_is_bulk_out(epd)) ++ result = usb_find_common_endpoints(iface_desc, &bulk_in, &bulk_out, NULL, NULL); ++ if (result) + goto failed; + + dev = interface_to_usbdev(interface); +@@ -95,6 +86,8 @@ static int prism2sta_probe_usb(struct us + } + + /* Initialize the hw data */ ++ hw->endp_in = usb_rcvbulkpipe(dev, bulk_in->bEndpointAddress); ++ hw->endp_out = usb_sndbulkpipe(dev, bulk_out->bEndpointAddress); + hfa384x_create(hw, dev); + hw->wlandev = wlandev; + diff --git a/queue-4.4/usb-core-add-helpers-to-retrieve-endpoints.patch b/queue-4.4/usb-core-add-helpers-to-retrieve-endpoints.patch new file mode 100644 index 00000000000..d33e63e9838 --- /dev/null +++ b/queue-4.4/usb-core-add-helpers-to-retrieve-endpoints.patch @@ -0,0 +1,166 @@ +From 66a359390e7e34f9a4c489467234b107b3d76169 Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Fri, 17 Mar 2017 11:35:30 +0100 +Subject: USB: core: add helpers to retrieve endpoints + +From: Johan Hovold + +commit 66a359390e7e34f9a4c489467234b107b3d76169 upstream. + +Many USB drivers iterate over the available endpoints to find required +endpoints of a specific type and direction. Typically the endpoints are +required for proper function and a missing endpoint should abort probe. + +To facilitate code reuse, add a helper to retrieve common endpoints +(bulk or interrupt, in or out) and four wrappers to find a single +endpoint. + +Note that the helpers are marked as __must_check to serve as a reminder +to always verify that all expected endpoints are indeed present. This +also means that any optional endpoints, typically need to be looked up +through separate calls. + +Signed-off-by: Johan Hovold +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/core/usb.c | 83 +++++++++++++++++++++++++++++++++++++++++++++++++ + include/linux/usb.h | 35 ++++++++++++++++++++ + 2 files changed, 118 insertions(+) + +--- a/drivers/usb/core/usb.c ++++ b/drivers/usb/core/usb.c +@@ -77,6 +77,89 @@ MODULE_PARM_DESC(autosuspend, "default a + + + /** ++ * usb_find_common_endpoints() -- look up common endpoint descriptors ++ * @alt: alternate setting to search ++ * @bulk_in: pointer to descriptor pointer, or NULL ++ * @bulk_out: pointer to descriptor pointer, or NULL ++ * @int_in: pointer to descriptor pointer, or NULL ++ * @int_out: pointer to descriptor pointer, or NULL ++ * ++ * Search the alternate setting's endpoint descriptors for the first bulk-in, ++ * bulk-out, interrupt-in and interrupt-out endpoints and return them in the ++ * provided pointers (unless they are NULL). ++ * ++ * If a requested endpoint is not found, the corresponding pointer is set to ++ * NULL. ++ * ++ * Return: Zero if all requested descriptors were found, or -ENXIO otherwise. ++ */ ++int usb_find_common_endpoints(struct usb_host_interface *alt, ++ struct usb_endpoint_descriptor **bulk_in, ++ struct usb_endpoint_descriptor **bulk_out, ++ struct usb_endpoint_descriptor **int_in, ++ struct usb_endpoint_descriptor **int_out) ++{ ++ struct usb_endpoint_descriptor *epd; ++ int i; ++ ++ if (bulk_in) ++ *bulk_in = NULL; ++ if (bulk_out) ++ *bulk_out = NULL; ++ if (int_in) ++ *int_in = NULL; ++ if (int_out) ++ *int_out = NULL; ++ ++ for (i = 0; i < alt->desc.bNumEndpoints; ++i) { ++ epd = &alt->endpoint[i].desc; ++ ++ switch (usb_endpoint_type(epd)) { ++ case USB_ENDPOINT_XFER_BULK: ++ if (usb_endpoint_dir_in(epd)) { ++ if (bulk_in && !*bulk_in) { ++ *bulk_in = epd; ++ break; ++ } ++ } else { ++ if (bulk_out && !*bulk_out) { ++ *bulk_out = epd; ++ break; ++ } ++ } ++ ++ continue; ++ case USB_ENDPOINT_XFER_INT: ++ if (usb_endpoint_dir_in(epd)) { ++ if (int_in && !*int_in) { ++ *int_in = epd; ++ break; ++ } ++ } else { ++ if (int_out && !*int_out) { ++ *int_out = epd; ++ break; ++ } ++ } ++ ++ continue; ++ default: ++ continue; ++ } ++ ++ if ((!bulk_in || *bulk_in) && ++ (!bulk_out || *bulk_out) && ++ (!int_in || *int_in) && ++ (!int_out || *int_out)) { ++ return 0; ++ } ++ } ++ ++ return -ENXIO; ++} ++EXPORT_SYMBOL_GPL(usb_find_common_endpoints); ++ ++/** + * usb_find_alt_setting() - Given a configuration, find the alternate setting + * for the given interface. + * @config: the configuration to search (not necessarily the current config). +--- a/include/linux/usb.h ++++ b/include/linux/usb.h +@@ -97,6 +97,41 @@ enum usb_interface_condition { + USB_INTERFACE_UNBINDING, + }; + ++int __must_check ++usb_find_common_endpoints(struct usb_host_interface *alt, ++ struct usb_endpoint_descriptor **bulk_in, ++ struct usb_endpoint_descriptor **bulk_out, ++ struct usb_endpoint_descriptor **int_in, ++ struct usb_endpoint_descriptor **int_out); ++ ++static inline int __must_check ++usb_find_bulk_in_endpoint(struct usb_host_interface *alt, ++ struct usb_endpoint_descriptor **bulk_in) ++{ ++ return usb_find_common_endpoints(alt, bulk_in, NULL, NULL, NULL); ++} ++ ++static inline int __must_check ++usb_find_bulk_out_endpoint(struct usb_host_interface *alt, ++ struct usb_endpoint_descriptor **bulk_out) ++{ ++ return usb_find_common_endpoints(alt, NULL, bulk_out, NULL, NULL); ++} ++ ++static inline int __must_check ++usb_find_int_in_endpoint(struct usb_host_interface *alt, ++ struct usb_endpoint_descriptor **int_in) ++{ ++ return usb_find_common_endpoints(alt, NULL, NULL, int_in, NULL); ++} ++ ++static inline int __must_check ++usb_find_int_out_endpoint(struct usb_host_interface *alt, ++ struct usb_endpoint_descriptor **int_out) ++{ ++ return usb_find_common_endpoints(alt, NULL, NULL, NULL, int_out); ++} ++ + /** + * struct usb_interface - what usb device drivers talk to + * @altsetting: array of interface structures, one for each alternate -- 2.47.3