From: Greg Kroah-Hartman Date: Sun, 6 Oct 2013 00:04:51 +0000 (-0700) Subject: 3.10-stable patches X-Git-Tag: v3.0.100~27 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=224e3d502b233b11cae2781319ce508045429089;p=thirdparty%2Fkernel%2Fstable-queue.git 3.10-stable patches 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 --- 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 index 00000000000..888d25532b2 --- /dev/null +++ b/queue-3.10/cciss-fix-info-leak-in-cciss_ioctl32_passthru.patch @@ -0,0 +1,35 @@ +From 58f09e00ae095e46ef9edfcf3a5fd9ccdfad065e Mon Sep 17 00:00:00 2001 +From: Dan Carpenter +Date: Tue, 24 Sep 2013 15:27:45 -0700 +Subject: cciss: fix info leak in cciss_ioctl32_passthru() + +From: Dan Carpenter + +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 +Acked-by: Mike Miller +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..c0199dcedd6 --- /dev/null +++ b/queue-3.10/cpqarray-fix-info-leak-in-ida_locked_ioctl.patch @@ -0,0 +1,34 @@ +From 627aad1c01da6f881e7f98d71fd928ca0c316b1a Mon Sep 17 00:00:00 2001 +From: Dan Carpenter +Date: Tue, 24 Sep 2013 15:27:44 -0700 +Subject: cpqarray: fix info leak in ida_locked_ioctl() + +From: Dan Carpenter + +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 +Acked-by: Mike Miller +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..3ff7ed22ca1 --- /dev/null +++ b/queue-3.10/hid-fix-data-access-in-implement.patch @@ -0,0 +1,243 @@ +From 27ce405039bfe6d3f4143415c638f56a3df77dca Mon Sep 17 00:00:00 2001 +From: Jiri Kosina +Date: Wed, 10 Jul 2013 19:56:27 +0200 +Subject: HID: fix data access in implement() + +From: Jiri Kosina + +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 +Acked-by: Gustavo Padovan +Signed-off-by: Jiri Kosina +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..a48b81a16d1 --- /dev/null +++ b/queue-3.10/hid-fix-unused-rsize-usage.patch @@ -0,0 +1,30 @@ +From bc197eedef1ae082ec662c64c3f4aa302821fb7a Mon Sep 17 00:00:00 2001 +From: Jiri Kosina +Date: Mon, 22 Jul 2013 17:11:44 +0200 +Subject: HID: fix unused rsize usage + +From: Jiri Kosina + +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 +Signed-off-by: Jiri Kosina +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..9c7fa9e0741 --- /dev/null +++ b/queue-3.10/mwifiex-fix-memory-corruption-when-unsetting-multicast-list.patch @@ -0,0 +1,75 @@ +From 6390d88529835a8ad3563fe01a5da89fa52d6db2 Mon Sep 17 00:00:00 2001 +From: Daniel Drake +Date: Fri, 14 Jun 2013 15:24:24 -0400 +Subject: mwifiex: fix memory corruption when unsetting multicast list + +From: Daniel Drake + +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 +Acked-by: Bing Zhao +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..86c57023304 --- /dev/null +++ b/queue-3.10/series @@ -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