]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.4-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 14 Sep 2020 12:18:08 +0000 (14:18 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 14 Sep 2020 12:18:08 +0000 (14:18 +0200)
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

queue-4.4/iio-accel-mma8452-fix-timestamp-alignment-and-prevent-data-leak.patch [new file with mode: 0644]
queue-4.4/series
queue-4.4/staging-wlan-ng-fix-out-of-bounds-read-in-prism2sta_probe_usb.patch [new file with mode: 0644]
queue-4.4/usb-core-add-helpers-to-retrieve-endpoints.patch [new file with mode: 0644]

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 (file)
index 0000000..614805f
--- /dev/null
@@ -0,0 +1,67 @@
+From 89226a296d816727405d3fea684ef69e7d388bd8 Mon Sep 17 00:00:00 2001
+From: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+Date: Wed, 22 Jul 2020 16:50:38 +0100
+Subject: iio:accel:mma8452: Fix timestamp alignment and prevent data leak.
+
+From: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+
+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 <lars@metafoo.de>
+Cc: Peter Meerwald <pmeerw@pmeerw.net>
+Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
+Cc: <Stable@vger.kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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:
index 8cf569f44eb16954a3b4e50a28c1152e7f76f6c4..731229f8393e2f9e2a5eb694ff7aceff409accac 100644 (file)
@@ -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 (file)
index 0000000..17ed3b4
--- /dev/null
@@ -0,0 +1,84 @@
+From fea22e159d51c766ba70473f473a0ec914cc7e92 Mon Sep 17 00:00:00 2001
+From: Rustam Kovhaev <rkovhaev@gmail.com>
+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 <rkovhaev@gmail.com>
+
+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 <rkovhaev@gmail.com>
+Cc: stable <stable@vger.kernel.org>
+Link: https://lore.kernel.org/r/20200804145614.104320-1-rkovhaev@gmail.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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 (file)
index 0000000..d33e63e
--- /dev/null
@@ -0,0 +1,166 @@
+From 66a359390e7e34f9a4c489467234b107b3d76169 Mon Sep 17 00:00:00 2001
+From: Johan Hovold <johan@kernel.org>
+Date: Fri, 17 Mar 2017 11:35:30 +0100
+Subject: USB: core: add helpers to retrieve endpoints
+
+From: Johan Hovold <johan@kernel.org>
+
+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 <johan@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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