]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.10-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 6 Oct 2013 00:04:51 +0000 (17:04 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 6 Oct 2013 00:04:51 +0000 (17:04 -0700)
added patches:
cciss-fix-info-leak-in-cciss_ioctl32_passthru.patch
cpqarray-fix-info-leak-in-ida_locked_ioctl.patch
hid-fix-data-access-in-implement.patch
hid-fix-unused-rsize-usage.patch
mwifiex-fix-memory-corruption-when-unsetting-multicast-list.patch

queue-3.10/cciss-fix-info-leak-in-cciss_ioctl32_passthru.patch [new file with mode: 0644]
queue-3.10/cpqarray-fix-info-leak-in-ida_locked_ioctl.patch [new file with mode: 0644]
queue-3.10/hid-fix-data-access-in-implement.patch [new file with mode: 0644]
queue-3.10/hid-fix-unused-rsize-usage.patch [new file with mode: 0644]
queue-3.10/mwifiex-fix-memory-corruption-when-unsetting-multicast-list.patch [new file with mode: 0644]
queue-3.10/series [new file with mode: 0644]

diff --git a/queue-3.10/cciss-fix-info-leak-in-cciss_ioctl32_passthru.patch b/queue-3.10/cciss-fix-info-leak-in-cciss_ioctl32_passthru.patch
new file mode 100644 (file)
index 0000000..888d255
--- /dev/null
@@ -0,0 +1,35 @@
+From 58f09e00ae095e46ef9edfcf3a5fd9ccdfad065e Mon Sep 17 00:00:00 2001
+From: Dan Carpenter <dan.carpenter@oracle.com>
+Date: Tue, 24 Sep 2013 15:27:45 -0700
+Subject: cciss: fix info leak in cciss_ioctl32_passthru()
+
+From: Dan Carpenter <dan.carpenter@oracle.com>
+
+commit 58f09e00ae095e46ef9edfcf3a5fd9ccdfad065e upstream.
+
+The arg64 struct has a hole after ->buf_size which isn't cleared.  Or if
+any of the calls to copy_from_user() fail then that would cause an
+information leak as well.
+
+This was assigned CVE-2013-2147.
+
+Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
+Acked-by: Mike Miller <mike.miller@hp.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/block/cciss.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/block/cciss.c
++++ b/drivers/block/cciss.c
+@@ -1189,6 +1189,7 @@ static int cciss_ioctl32_passthru(struct
+       int err;
+       u32 cp;
++      memset(&arg64, 0, sizeof(arg64));
+       err = 0;
+       err |=
+           copy_from_user(&arg64.LUN_info, &arg32->LUN_info,
diff --git a/queue-3.10/cpqarray-fix-info-leak-in-ida_locked_ioctl.patch b/queue-3.10/cpqarray-fix-info-leak-in-ida_locked_ioctl.patch
new file mode 100644 (file)
index 0000000..c0199dc
--- /dev/null
@@ -0,0 +1,34 @@
+From 627aad1c01da6f881e7f98d71fd928ca0c316b1a Mon Sep 17 00:00:00 2001
+From: Dan Carpenter <dan.carpenter@oracle.com>
+Date: Tue, 24 Sep 2013 15:27:44 -0700
+Subject: cpqarray: fix info leak in ida_locked_ioctl()
+
+From: Dan Carpenter <dan.carpenter@oracle.com>
+
+commit 627aad1c01da6f881e7f98d71fd928ca0c316b1a upstream.
+
+The pciinfo struct has a two byte hole after ->dev_fn so stack
+information could be leaked to the user.
+
+This was assigned CVE-2013-2147.
+
+Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
+Acked-by: Mike Miller <mike.miller@hp.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/block/cpqarray.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/block/cpqarray.c
++++ b/drivers/block/cpqarray.c
+@@ -1193,6 +1193,7 @@ out_passthru:
+               ida_pci_info_struct pciinfo;
+               if (!arg) return -EINVAL;
++              memset(&pciinfo, 0, sizeof(pciinfo));
+               pciinfo.bus = host->pci_dev->bus->number;
+               pciinfo.dev_fn = host->pci_dev->devfn;
+               pciinfo.board_id = host->board_id;
diff --git a/queue-3.10/hid-fix-data-access-in-implement.patch b/queue-3.10/hid-fix-data-access-in-implement.patch
new file mode 100644 (file)
index 0000000..3ff7ed2
--- /dev/null
@@ -0,0 +1,243 @@
+From 27ce405039bfe6d3f4143415c638f56a3df77dca Mon Sep 17 00:00:00 2001
+From: Jiri Kosina <jkosina@suse.cz>
+Date: Wed, 10 Jul 2013 19:56:27 +0200
+Subject: HID: fix data access in implement()
+
+From: Jiri Kosina <jkosina@suse.cz>
+
+commit 27ce405039bfe6d3f4143415c638f56a3df77dca upstream.
+
+implement() is setting bytes in LE data stream. In case the data is not
+aligned to 64bits, it reads past the allocated buffer. It doesn't really
+change any value there (it's properly bitmasked), but in case that this
+read past the boundary hits a page boundary, pagefault happens when
+accessing 64bits of 'x' in implement(), and kernel oopses.
+
+This happens much more often when numbered reports are in use, as the
+initial 8bit skip in the buffer makes the whole process work on values
+which are not aligned to 64bits.
+
+This problem dates back to attempts in 2005 and 2006 to make implement()
+and extract() as generic as possible, and even back then the problem
+was realized by Adam Kroperlin, but falsely assumed to be impossible
+to cause any harm:
+
+  http://www.mail-archive.com/linux-usb-devel@lists.sourceforge.net/msg47690.html
+
+I have made several attempts at fixing it "on the spot" directly in
+implement(), but the results were horrible; the special casing for processing
+last 64bit chunk and switching to different math makes it unreadable mess.
+
+I therefore took a path to allocate a few bytes more which will never make
+it into final report, but are there as a cushion for all the 64bit math
+operations happening in implement() and extract().
+
+All callers of hid_output_report() are converted at the same time to allocate
+the buffer by newly introduced hid_alloc_report_buf() helper.
+
+Bruno noticed that the whole raw_size test can be dropped as well, as
+hid_alloc_report_buf() makes sure that the buffer is always of a proper
+size.
+
+Reviewed-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
+Acked-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
+Signed-off-by: Jiri Kosina <jkosina@suse.cz>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/hid/hid-core.c            |   19 ++++++++++++++++++-
+ drivers/hid/hid-logitech-dj.c     |   12 ++++++++++--
+ drivers/hid/hid-picolcd_debugfs.c |   23 ++++++++++++-----------
+ drivers/hid/usbhid/hid-core.c     |    5 ++---
+ include/linux/hid.h               |    1 +
+ net/bluetooth/hidp/core.c         |   14 +++++++++-----
+ 6 files changed, 52 insertions(+), 22 deletions(-)
+
+--- a/drivers/hid/hid-core.c
++++ b/drivers/hid/hid-core.c
+@@ -1188,7 +1188,8 @@ static void hid_output_field(const struc
+ }
+ /*
+- * Create a report.
++ * Create a report. 'data' has to be allocated using
++ * hid_alloc_report_buf() so that it has proper size.
+  */
+ void hid_output_report(struct hid_report *report, __u8 *data)
+@@ -1205,6 +1206,22 @@ void hid_output_report(struct hid_report
+ EXPORT_SYMBOL_GPL(hid_output_report);
+ /*
++ * Allocator for buffer that is going to be passed to hid_output_report()
++ */
++u8 *hid_alloc_report_buf(struct hid_report *report, gfp_t flags)
++{
++      /*
++       * 7 extra bytes are necessary to achieve proper functionality
++       * of implement() working on 8 byte chunks
++       */
++
++      int len = ((report->size - 1) >> 3) + 1 + (report->id > 0) + 7;
++
++      return kmalloc(len, flags);
++}
++EXPORT_SYMBOL_GPL(hid_alloc_report_buf);
++
++/*
+  * Set a field value. The report this field belongs to has to be
+  * created and transferred to the device, to set this value in the
+  * device.
+--- a/drivers/hid/hid-logitech-dj.c
++++ b/drivers/hid/hid-logitech-dj.c
+@@ -574,7 +574,7 @@ static int logi_dj_ll_input_event(struct
+       struct hid_field *field;
+       struct hid_report *report;
+-      unsigned char data[8];
++      unsigned char *data;
+       int offset;
+       dbg_hid("%s: %s, type:%d | code:%d | value:%d\n",
+@@ -590,6 +590,13 @@ static int logi_dj_ll_input_event(struct
+               return -1;
+       }
+       hid_set_field(field, offset, value);
++
++      data = hid_alloc_report_buf(field->report, GFP_KERNEL);
++      if (!data) {
++              dev_warn(&dev->dev, "failed to allocate report buf memory\n");
++              return -1;
++      }
++
+       hid_output_report(field->report, &data[0]);
+       output_report_enum = &dj_rcv_hiddev->report_enum[HID_OUTPUT_REPORT];
+@@ -600,8 +607,9 @@ static int logi_dj_ll_input_event(struct
+       hid_hw_request(dj_rcv_hiddev, report, HID_REQ_SET_REPORT);
+-      return 0;
++      kfree(data);
++      return 0;
+ }
+ static int logi_dj_ll_start(struct hid_device *hid)
+--- a/drivers/hid/hid-picolcd_debugfs.c
++++ b/drivers/hid/hid-picolcd_debugfs.c
+@@ -394,7 +394,7 @@ static void dump_buff_as_hex(char *dst,
+ void picolcd_debug_out_report(struct picolcd_data *data,
+               struct hid_device *hdev, struct hid_report *report)
+ {
+-      u8 raw_data[70];
++      u8 *raw_data;
+       int raw_size = (report->size >> 3) + 1;
+       char *buff;
+ #define BUFF_SZ 256
+@@ -407,20 +407,20 @@ void picolcd_debug_out_report(struct pic
+       if (!buff)
+               return;
+-      snprintf(buff, BUFF_SZ, "\nout report %d (size %d) =  ",
+-                      report->id, raw_size);
+-      hid_debug_event(hdev, buff);
+-      if (raw_size + 5 > sizeof(raw_data)) {
++      raw_data = hid_alloc_report_buf(report, GFP_ATOMIC);
++      if (!raw_data) {
+               kfree(buff);
+-              hid_debug_event(hdev, " TOO BIG\n");
+               return;
+-      } else {
+-              raw_data[0] = report->id;
+-              hid_output_report(report, raw_data);
+-              dump_buff_as_hex(buff, BUFF_SZ, raw_data, raw_size);
+-              hid_debug_event(hdev, buff);
+       }
++      snprintf(buff, BUFF_SZ, "\nout report %d (size %d) =  ",
++                      report->id, raw_size);
++      hid_debug_event(hdev, buff);
++      raw_data[0] = report->id;
++      hid_output_report(report, raw_data);
++      dump_buff_as_hex(buff, BUFF_SZ, raw_data, raw_size);
++      hid_debug_event(hdev, buff);
++
+       switch (report->id) {
+       case REPORT_LED_STATE:
+               /* 1 data byte with GPO state */
+@@ -644,6 +644,7 @@ void picolcd_debug_out_report(struct pic
+               break;
+       }
+       wake_up_interruptible(&hdev->debug_wait);
++      kfree(raw_data);
+       kfree(buff);
+ }
+--- a/drivers/hid/usbhid/hid-core.c
++++ b/drivers/hid/usbhid/hid-core.c
+@@ -535,7 +535,6 @@ static void __usbhid_submit_report(struc
+ {
+       int head;
+       struct usbhid_device *usbhid = hid->driver_data;
+-      int len = ((report->size - 1) >> 3) + 1 + (report->id > 0);
+       if ((hid->quirks & HID_QUIRK_NOGET) && dir == USB_DIR_IN)
+               return;
+@@ -546,7 +545,7 @@ static void __usbhid_submit_report(struc
+                       return;
+               }
+-              usbhid->out[usbhid->outhead].raw_report = kmalloc(len, GFP_ATOMIC);
++              usbhid->out[usbhid->outhead].raw_report = hid_alloc_report_buf(report, GFP_ATOMIC);
+               if (!usbhid->out[usbhid->outhead].raw_report) {
+                       hid_warn(hid, "output queueing failed\n");
+                       return;
+@@ -595,7 +594,7 @@ static void __usbhid_submit_report(struc
+       }
+       if (dir == USB_DIR_OUT) {
+-              usbhid->ctrl[usbhid->ctrlhead].raw_report = kmalloc(len, GFP_ATOMIC);
++              usbhid->ctrl[usbhid->ctrlhead].raw_report = hid_alloc_report_buf(report, GFP_ATOMIC);
+               if (!usbhid->ctrl[usbhid->ctrlhead].raw_report) {
+                       hid_warn(hid, "control queueing failed\n");
+                       return;
+--- a/include/linux/hid.h
++++ b/include/linux/hid.h
+@@ -746,6 +746,7 @@ struct hid_field *hidinput_get_led_field
+ unsigned int hidinput_count_leds(struct hid_device *hid);
+ __s32 hidinput_calc_abs_res(const struct hid_field *field, __u16 code);
+ void hid_output_report(struct hid_report *report, __u8 *data);
++u8 *hid_alloc_report_buf(struct hid_report *report, gfp_t flags);
+ struct hid_device *hid_allocate_device(void);
+ struct hid_report *hid_register_report(struct hid_device *device, unsigned type, unsigned id);
+ int hid_parse_report(struct hid_device *hid, __u8 *start, unsigned size);
+--- a/net/bluetooth/hidp/core.c
++++ b/net/bluetooth/hidp/core.c
+@@ -231,17 +231,21 @@ static void hidp_input_report(struct hid
+ static int hidp_send_report(struct hidp_session *session, struct hid_report *report)
+ {
+-      unsigned char buf[32], hdr;
+-      int rsize;
++      unsigned char hdr;
++      u8 *buf;
++      int rsize, ret;
+-      rsize = ((report->size - 1) >> 3) + 1 + (report->id > 0);
+-      if (rsize > sizeof(buf))
++      buf = hid_alloc_report_buf(report, GFP_ATOMIC);
++      if (!buf)
+               return -EIO;
+       hid_output_report(report, buf);
+       hdr = HIDP_TRANS_DATA | HIDP_DATA_RTYPE_OUPUT;
+-      return hidp_send_intr_message(session, hdr, buf, rsize);
++      ret = hidp_send_intr_message(session, hdr, buf, rsize);
++
++      kfree(buf);
++      return ret;
+ }
+ static int hidp_get_raw_report(struct hid_device *hid,
diff --git a/queue-3.10/hid-fix-unused-rsize-usage.patch b/queue-3.10/hid-fix-unused-rsize-usage.patch
new file mode 100644 (file)
index 0000000..a48b81a
--- /dev/null
@@ -0,0 +1,30 @@
+From bc197eedef1ae082ec662c64c3f4aa302821fb7a Mon Sep 17 00:00:00 2001
+From: Jiri Kosina <jkosina@suse.cz>
+Date: Mon, 22 Jul 2013 17:11:44 +0200
+Subject: HID: fix unused rsize usage
+
+From: Jiri Kosina <jkosina@suse.cz>
+
+commit bc197eedef1ae082ec662c64c3f4aa302821fb7a upstream.
+
+27ce4050 ("HID: fix data access in implement()") by mistake removed
+a setting of buffer size in hidp. Fix that by putting it back.
+
+Reported-by: kbuild test robot <fengguang.wu@intel.com>
+Signed-off-by: Jiri Kosina <jkosina@suse.cz>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ net/bluetooth/hidp/core.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/net/bluetooth/hidp/core.c
++++ b/net/bluetooth/hidp/core.c
+@@ -242,6 +242,7 @@ static int hidp_send_report(struct hidp_
+       hid_output_report(report, buf);
+       hdr = HIDP_TRANS_DATA | HIDP_DATA_RTYPE_OUPUT;
++      rsize = ((report->size - 1) >> 3) + 1 + (report->id > 0);
+       ret = hidp_send_intr_message(session, hdr, buf, rsize);
+       kfree(buf);
diff --git a/queue-3.10/mwifiex-fix-memory-corruption-when-unsetting-multicast-list.patch b/queue-3.10/mwifiex-fix-memory-corruption-when-unsetting-multicast-list.patch
new file mode 100644 (file)
index 0000000..9c7fa9e
--- /dev/null
@@ -0,0 +1,75 @@
+From 6390d88529835a8ad3563fe01a5da89fa52d6db2 Mon Sep 17 00:00:00 2001
+From: Daniel Drake <dsd@laptop.org>
+Date: Fri, 14 Jun 2013 15:24:24 -0400
+Subject: mwifiex: fix memory corruption when unsetting multicast list
+
+From: Daniel Drake <dsd@laptop.org>
+
+commit 6390d88529835a8ad3563fe01a5da89fa52d6db2 upstream.
+
+When trying to unset a previously-set multicast list (i.e. the new list
+has 0 entries), mwifiex_set_multicast_list() was calling down to
+mwifiex_request_set_multicast_list() while leaving
+mcast_list.num_multicast_addr as an uninitialized value.
+
+We were arriving at mwifiex_cmd_mac_multicast_adr() which would then
+proceed to do an often huge memcpy of
+mcast_list.num_multicast_addr*ETH_ALEN bytes, causing memory corruption
+and hard to debug crashes.
+
+Fix this by setting mcast_list.num_multicast_addr to 0 when no multicast
+list is provided. Similarly, fix up the logic in
+mwifiex_request_set_multicast_list() to unset the multicast list that
+was previously sent to the hardware in such cases.
+
+Signed-off-by: Daniel Drake <dsd@laptop.org>
+Acked-by: Bing Zhao <bzhao@marvell.com>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/net/wireless/mwifiex/main.c      |    5 ++---
+ drivers/net/wireless/mwifiex/sta_ioctl.c |   18 ++++++++----------
+ 2 files changed, 10 insertions(+), 13 deletions(-)
+
+--- a/drivers/net/wireless/mwifiex/main.c
++++ b/drivers/net/wireless/mwifiex/main.c
+@@ -559,9 +559,8 @@ static void mwifiex_set_multicast_list(s
+               mcast_list.mode = MWIFIEX_ALL_MULTI_MODE;
+       } else {
+               mcast_list.mode = MWIFIEX_MULTICAST_MODE;
+-              if (netdev_mc_count(dev))
+-                      mcast_list.num_multicast_addr =
+-                              mwifiex_copy_mcast_addr(&mcast_list, dev);
++              mcast_list.num_multicast_addr =
++                      mwifiex_copy_mcast_addr(&mcast_list, dev);
+       }
+       mwifiex_request_set_multicast_list(priv, &mcast_list);
+ }
+--- a/drivers/net/wireless/mwifiex/sta_ioctl.c
++++ b/drivers/net/wireless/mwifiex/sta_ioctl.c
+@@ -104,16 +104,14 @@ int mwifiex_request_set_multicast_list(s
+               } else {
+                       priv->curr_pkt_filter &=
+                               ~HostCmd_ACT_MAC_ALL_MULTICAST_ENABLE;
+-                      if (mcast_list->num_multicast_addr) {
+-                              dev_dbg(priv->adapter->dev,
+-                                      "info: Set multicast list=%d\n",
+-                                     mcast_list->num_multicast_addr);
+-                              /* Send multicast addresses to firmware */
+-                              ret = mwifiex_send_cmd_async(priv,
+-                                      HostCmd_CMD_MAC_MULTICAST_ADR,
+-                                      HostCmd_ACT_GEN_SET, 0,
+-                                      mcast_list);
+-                      }
++                      dev_dbg(priv->adapter->dev,
++                              "info: Set multicast list=%d\n",
++                              mcast_list->num_multicast_addr);
++                      /* Send multicast addresses to firmware */
++                      ret = mwifiex_send_cmd_async(priv,
++                              HostCmd_CMD_MAC_MULTICAST_ADR,
++                              HostCmd_ACT_GEN_SET, 0,
++                              mcast_list);
+               }
+       }
+       dev_dbg(priv->adapter->dev,
diff --git a/queue-3.10/series b/queue-3.10/series
new file mode 100644 (file)
index 0000000..86c5702
--- /dev/null
@@ -0,0 +1,5 @@
+mwifiex-fix-memory-corruption-when-unsetting-multicast-list.patch
+cpqarray-fix-info-leak-in-ida_locked_ioctl.patch
+cciss-fix-info-leak-in-cciss_ioctl32_passthru.patch
+hid-fix-data-access-in-implement.patch
+hid-fix-unused-rsize-usage.patch