]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.18-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 3 Aug 2017 22:43:56 +0000 (15:43 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 3 Aug 2017 22:43:56 +0000 (15:43 -0700)
added patches:
ipmi-watchdog-fix-watchdog-timeout-set-on-reboot.patch
ipv6-fix-possible-deadlock-in-ip6_fl_purge-ip6_fl_gc.patch
isdn-fix-a-sleep-in-atomic-bug.patch
isdn-i4l-fix-buffer-overflow.patch
kaweth-fix-firmware-download.patch
kaweth-fix-oops-upon-failed-memory-allocation.patch
mailbox-always-wait-in-mbox_send_message-for-blocking-tx-mode.patch
mailbox-handle-empty-message-in-tx_tick.patch
mailbox-skip-complete-wait-event-if-timer-expired.patch
mpt3sas-don-t-overreach-ioc-reply_post-during-initialization.patch
net-sched-fix-soft-lockup-in-tc_classify.patch
net-sctp-fix-race-for-one-to-many-sockets-in-sendmsg-s-auto-associate.patch
sh_eth-fix-ethtool-operation-crash-when-net-device-is-down.patch
string-provide-strscpy.patch
strscpy-zero-any-trailing-garbage-bytes-in-the-destination.patch
wil6210-fix-deadlock-when-using-fw_no_recovery-option.patch

17 files changed:
queue-3.18/ipmi-watchdog-fix-watchdog-timeout-set-on-reboot.patch [new file with mode: 0644]
queue-3.18/ipv6-fix-possible-deadlock-in-ip6_fl_purge-ip6_fl_gc.patch [new file with mode: 0644]
queue-3.18/isdn-fix-a-sleep-in-atomic-bug.patch [new file with mode: 0644]
queue-3.18/isdn-i4l-fix-buffer-overflow.patch [new file with mode: 0644]
queue-3.18/kaweth-fix-firmware-download.patch [new file with mode: 0644]
queue-3.18/kaweth-fix-oops-upon-failed-memory-allocation.patch [new file with mode: 0644]
queue-3.18/mailbox-always-wait-in-mbox_send_message-for-blocking-tx-mode.patch [new file with mode: 0644]
queue-3.18/mailbox-handle-empty-message-in-tx_tick.patch [new file with mode: 0644]
queue-3.18/mailbox-skip-complete-wait-event-if-timer-expired.patch [new file with mode: 0644]
queue-3.18/mpt3sas-don-t-overreach-ioc-reply_post-during-initialization.patch [new file with mode: 0644]
queue-3.18/net-sched-fix-soft-lockup-in-tc_classify.patch [new file with mode: 0644]
queue-3.18/net-sctp-fix-race-for-one-to-many-sockets-in-sendmsg-s-auto-associate.patch [new file with mode: 0644]
queue-3.18/series
queue-3.18/sh_eth-fix-ethtool-operation-crash-when-net-device-is-down.patch [new file with mode: 0644]
queue-3.18/string-provide-strscpy.patch [new file with mode: 0644]
queue-3.18/strscpy-zero-any-trailing-garbage-bytes-in-the-destination.patch [new file with mode: 0644]
queue-3.18/wil6210-fix-deadlock-when-using-fw_no_recovery-option.patch [new file with mode: 0644]

diff --git a/queue-3.18/ipmi-watchdog-fix-watchdog-timeout-set-on-reboot.patch b/queue-3.18/ipmi-watchdog-fix-watchdog-timeout-set-on-reboot.patch
new file mode 100644 (file)
index 0000000..23206c7
--- /dev/null
@@ -0,0 +1,43 @@
+From 860f01e96981a68553f3ca49f574ff14fe955e72 Mon Sep 17 00:00:00 2001
+From: Valentin Vidic <Valentin.Vidic@CARNet.hr>
+Date: Fri, 5 May 2017 21:07:33 +0200
+Subject: ipmi/watchdog: fix watchdog timeout set on reboot
+
+From: Valentin Vidic <Valentin.Vidic@CARNet.hr>
+
+commit 860f01e96981a68553f3ca49f574ff14fe955e72 upstream.
+
+systemd by default starts watchdog on reboot and sets the timer to
+ShutdownWatchdogSec=10min.  Reboot handler in ipmi_watchdog than reduces
+the timer to 120s which is not enough time to boot a Xen machine with
+a lot of RAM.  As a result the machine is rebooted the second time
+during the long run of (XEN) Scrubbing Free RAM.....
+
+Fix this by setting the timer to 120s only if it was previously
+set to a low value.
+
+Signed-off-by: Valentin Vidic <Valentin.Vidic@CARNet.hr>
+Signed-off-by: Corey Minyard <cminyard@mvista.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/char/ipmi/ipmi_watchdog.c |    7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+--- a/drivers/char/ipmi/ipmi_watchdog.c
++++ b/drivers/char/ipmi/ipmi_watchdog.c
+@@ -1156,10 +1156,11 @@ static int wdog_reboot_handler(struct no
+                       ipmi_watchdog_state = WDOG_TIMEOUT_NONE;
+                       ipmi_set_timeout(IPMI_SET_TIMEOUT_NO_HB);
+               } else if (ipmi_watchdog_state != WDOG_TIMEOUT_NONE) {
+-                      /* Set a long timer to let the reboot happens, but
+-                         reboot if it hangs, but only if the watchdog
++                      /* Set a long timer to let the reboot happen or
++                         reset if it hangs, but only if the watchdog
+                          timer was already running. */
+-                      timeout = 120;
++                      if (timeout < 120)
++                              timeout = 120;
+                       pretimeout = 0;
+                       ipmi_watchdog_state = WDOG_TIMEOUT_RESET;
+                       ipmi_set_timeout(IPMI_SET_TIMEOUT_NO_HB);
diff --git a/queue-3.18/ipv6-fix-possible-deadlock-in-ip6_fl_purge-ip6_fl_gc.patch b/queue-3.18/ipv6-fix-possible-deadlock-in-ip6_fl_purge-ip6_fl_gc.patch
new file mode 100644 (file)
index 0000000..32e1c8c
--- /dev/null
@@ -0,0 +1,76 @@
+From 4762fb980465463734f02c67c67f40beb8903f73 Mon Sep 17 00:00:00 2001
+From: Jan Stancek <jstancek@redhat.com>
+Date: Wed, 11 Feb 2015 14:06:23 +0100
+Subject: ipv6: fix possible deadlock in ip6_fl_purge / ip6_fl_gc
+
+From: Jan Stancek <jstancek@redhat.com>
+
+commit 4762fb980465463734f02c67c67f40beb8903f73 upstream.
+
+Use spin_lock_bh in ip6_fl_purge() to prevent following potentially
+deadlock scenario between ip6_fl_purge() and ip6_fl_gc() timer.
+
+  =================================
+  [ INFO: inconsistent lock state ]
+  3.19.0 #1 Not tainted
+  ---------------------------------
+  inconsistent {SOFTIRQ-ON-W} -> {IN-SOFTIRQ-W} usage.
+  swapper/5/0 [HC0[0]:SC1[1]:HE1:SE0] takes:
+   (ip6_fl_lock){+.?...}, at: [<ffffffff8171155d>] ip6_fl_gc+0x2d/0x180
+  {SOFTIRQ-ON-W} state was registered at:
+    [<ffffffff810ee9a0>] __lock_acquire+0x4a0/0x10b0
+    [<ffffffff810efd54>] lock_acquire+0xc4/0x2b0
+    [<ffffffff81751d2d>] _raw_spin_lock+0x3d/0x80
+    [<ffffffff81711798>] ip6_flowlabel_net_exit+0x28/0x110
+    [<ffffffff815f9759>] ops_exit_list.isra.1+0x39/0x60
+    [<ffffffff815fa320>] cleanup_net+0x100/0x1e0
+    [<ffffffff810ad80a>] process_one_work+0x20a/0x830
+    [<ffffffff810adf4b>] worker_thread+0x11b/0x460
+    [<ffffffff810b42f4>] kthread+0x104/0x120
+    [<ffffffff81752bfc>] ret_from_fork+0x7c/0xb0
+  irq event stamp: 84640
+  hardirqs last  enabled at (84640): [<ffffffff81752080>] _raw_spin_unlock_irq+0x30/0x50
+  hardirqs last disabled at (84639): [<ffffffff81751eff>] _raw_spin_lock_irq+0x1f/0x80
+  softirqs last  enabled at (84628): [<ffffffff81091ad1>] _local_bh_enable+0x21/0x50
+  softirqs last disabled at (84629): [<ffffffff81093b7d>] irq_exit+0x12d/0x150
+
+  other info that might help us debug this:
+   Possible unsafe locking scenario:
+
+         CPU0
+         ----
+    lock(ip6_fl_lock);
+    <Interrupt>
+      lock(ip6_fl_lock);
+
+   *** DEADLOCK ***
+
+Signed-off-by: Jan Stancek <jstancek@redhat.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Amit Pundir <amit.pundir@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ net/ipv6/ip6_flowlabel.c |    4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/net/ipv6/ip6_flowlabel.c
++++ b/net/ipv6/ip6_flowlabel.c
+@@ -172,7 +172,7 @@ static void __net_exit ip6_fl_purge(stru
+ {
+       int i;
+-      spin_lock(&ip6_fl_lock);
++      spin_lock_bh(&ip6_fl_lock);
+       for (i = 0; i <= FL_HASH_MASK; i++) {
+               struct ip6_flowlabel *fl;
+               struct ip6_flowlabel __rcu **flp;
+@@ -190,7 +190,7 @@ static void __net_exit ip6_fl_purge(stru
+                       flp = &fl->next;
+               }
+       }
+-      spin_unlock(&ip6_fl_lock);
++      spin_unlock_bh(&ip6_fl_lock);
+ }
+ static struct ip6_flowlabel *fl_intern(struct net *net,
diff --git a/queue-3.18/isdn-fix-a-sleep-in-atomic-bug.patch b/queue-3.18/isdn-fix-a-sleep-in-atomic-bug.patch
new file mode 100644 (file)
index 0000000..307b719
--- /dev/null
@@ -0,0 +1,40 @@
+From e8f4ae85439f34bec3b0ab69223a41809dab28c9 Mon Sep 17 00:00:00 2001
+From: Jia-Ju Bai <baijiaju1990@163.com>
+Date: Wed, 31 May 2017 09:40:11 +0800
+Subject: isdn: Fix a sleep-in-atomic bug
+
+From: Jia-Ju Bai <baijiaju1990@163.com>
+
+commit e8f4ae85439f34bec3b0ab69223a41809dab28c9 upstream.
+
+The driver may sleep under a spin lock, the function call path is:
+isdn_ppp_mp_receive (acquire the lock)
+  isdn_ppp_mp_reassembly
+    isdn_ppp_push_higher
+      isdn_ppp_decompress
+        isdn_ppp_ccp_reset_trans
+          isdn_ppp_ccp_reset_alloc_state
+            kzalloc(GFP_KERNEL) --> may sleep
+
+To fixed it, the "GFP_KERNEL" is replaced with "GFP_ATOMIC".
+
+Signed-off-by: Jia-Ju Bai <baijiaju1990@163.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Amit Pundir <amit.pundir@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/isdn/i4l/isdn_ppp.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/isdn/i4l/isdn_ppp.c
++++ b/drivers/isdn/i4l/isdn_ppp.c
+@@ -2364,7 +2364,7 @@ static struct ippp_ccp_reset_state *isdn
+                      id);
+               return NULL;
+       } else {
+-              rs = kzalloc(sizeof(struct ippp_ccp_reset_state), GFP_KERNEL);
++              rs = kzalloc(sizeof(struct ippp_ccp_reset_state), GFP_ATOMIC);
+               if (!rs)
+                       return NULL;
+               rs->state = CCPResetIdle;
diff --git a/queue-3.18/isdn-i4l-fix-buffer-overflow.patch b/queue-3.18/isdn-i4l-fix-buffer-overflow.patch
new file mode 100644 (file)
index 0000000..0a9d0b0
--- /dev/null
@@ -0,0 +1,53 @@
+From 9f5af546e6acc30f075828cb58c7f09665033967 Mon Sep 17 00:00:00 2001
+From: Annie Cherkaev <annie.cherk@gmail.com>
+Date: Sat, 15 Jul 2017 15:08:58 -0600
+Subject: isdn/i4l: fix buffer overflow
+
+From: Annie Cherkaev <annie.cherk@gmail.com>
+
+commit 9f5af546e6acc30f075828cb58c7f09665033967 upstream.
+
+This fixes a potential buffer overflow in isdn_net.c caused by an
+unbounded strcpy.
+
+[ ISDN seems to be effectively unmaintained, and the I4L driver in
+  particular is long deprecated, but in case somebody uses this..
+    - Linus ]
+
+Signed-off-by: Jiten Thakkar <jitenmt@gmail.com>
+Signed-off-by: Annie Cherkaev <annie.cherk@gmail.com>
+Cc: Karsten Keil <isdn@linux-pingi.de>
+Cc: Kees Cook <keescook@chromium.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/isdn/i4l/isdn_common.c |    1 +
+ drivers/isdn/i4l/isdn_net.c    |    5 ++---
+ 2 files changed, 3 insertions(+), 3 deletions(-)
+
+--- a/drivers/isdn/i4l/isdn_common.c
++++ b/drivers/isdn/i4l/isdn_common.c
+@@ -1379,6 +1379,7 @@ isdn_ioctl(struct file *file, uint cmd,
+                       if (arg) {
+                               if (copy_from_user(bname, argp, sizeof(bname) - 1))
+                                       return -EFAULT;
++                              bname[sizeof(bname)-1] = 0;
+                       } else
+                               return -EINVAL;
+                       ret = mutex_lock_interruptible(&dev->mtx);
+--- a/drivers/isdn/i4l/isdn_net.c
++++ b/drivers/isdn/i4l/isdn_net.c
+@@ -2644,10 +2644,9 @@ isdn_net_newslave(char *parm)
+       char newname[10];
+       if (p) {
+-              /* Slave-Name MUST not be empty */
+-              if (!strlen(p + 1))
++              /* Slave-Name MUST not be empty or overflow 'newname' */
++              if (strscpy(newname, p + 1, sizeof(newname)) <= 0)
+                       return NULL;
+-              strcpy(newname, p + 1);
+               *p = 0;
+               /* Master must already exist */
+               if (!(n = isdn_net_findif(parm)))
diff --git a/queue-3.18/kaweth-fix-firmware-download.patch b/queue-3.18/kaweth-fix-firmware-download.patch
new file mode 100644 (file)
index 0000000..39bd30c
--- /dev/null
@@ -0,0 +1,40 @@
+From 60bcabd080f53561efa9288be45c128feda1a8bb Mon Sep 17 00:00:00 2001
+From: Oliver Neukum <oneukum@suse.com>
+Date: Wed, 17 Aug 2016 15:51:55 +0200
+Subject: kaweth: fix firmware download
+
+From: Oliver Neukum <oneukum@suse.com>
+
+commit 60bcabd080f53561efa9288be45c128feda1a8bb upstream.
+
+This fixes the oops discovered by the Umap2 project and Alan Stern.
+The intf member needs to be set before the firmware is downloaded.
+
+Signed-off-by: Oliver Neukum <oneukum@suse.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Amit Pundir <amit.pundir@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/net/usb/kaweth.c |    3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+--- a/drivers/net/usb/kaweth.c
++++ b/drivers/net/usb/kaweth.c
+@@ -1029,6 +1029,7 @@ static int kaweth_probe(
+       kaweth = netdev_priv(netdev);
+       kaweth->dev = udev;
+       kaweth->net = netdev;
++      kaweth->intf = intf;
+       spin_lock_init(&kaweth->device_lock);
+       init_waitqueue_head(&kaweth->term_wait);
+@@ -1139,8 +1140,6 @@ err_fw:
+       dev_dbg(dev, "Initializing net device.\n");
+-      kaweth->intf = intf;
+-
+       kaweth->tx_urb = usb_alloc_urb(0, GFP_KERNEL);
+       if (!kaweth->tx_urb)
+               goto err_free_netdev;
diff --git a/queue-3.18/kaweth-fix-oops-upon-failed-memory-allocation.patch b/queue-3.18/kaweth-fix-oops-upon-failed-memory-allocation.patch
new file mode 100644 (file)
index 0000000..f9d1518
--- /dev/null
@@ -0,0 +1,50 @@
+From 575ced7f8090c1a4e91e2daf8da9352a6a1fc7a7 Mon Sep 17 00:00:00 2001
+From: Oliver Neukum <oneukum@suse.com>
+Date: Wed, 17 Aug 2016 15:51:56 +0200
+Subject: kaweth: fix oops upon failed memory allocation
+
+From: Oliver Neukum <oneukum@suse.com>
+
+commit 575ced7f8090c1a4e91e2daf8da9352a6a1fc7a7 upstream.
+
+Just return an error upon failure.
+
+Signed-off-by: Oliver Neukum <oneukum@suse.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Amit Pundir <amit.pundir@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/net/usb/kaweth.c |    7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+--- a/drivers/net/usb/kaweth.c
++++ b/drivers/net/usb/kaweth.c
+@@ -1009,6 +1009,7 @@ static int kaweth_probe(
+       struct net_device *netdev;
+       const eth_addr_t bcast_addr = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
+       int result = 0;
++      int rv = -EIO;
+       dev_dbg(dev,
+               "Kawasaki Device Probe (Device number:%d): 0x%4.4x:0x%4.4x:0x%4.4x\n",
+@@ -1049,6 +1050,10 @@ static int kaweth_probe(
+               /* Download the firmware */
+               dev_info(dev, "Downloading firmware...\n");
+               kaweth->firmware_buf = (__u8 *)__get_free_page(GFP_KERNEL);
++              if (!kaweth->firmware_buf) {
++                      rv = -ENOMEM;
++                      goto err_free_netdev;
++              }
+               if ((result = kaweth_download_firmware(kaweth,
+                                                     "kaweth/new_code.bin",
+                                                     100,
+@@ -1209,7 +1214,7 @@ err_only_tx:
+ err_free_netdev:
+       free_netdev(netdev);
+-      return -EIO;
++      return rv;
+ }
+ /****************************************************************
diff --git a/queue-3.18/mailbox-always-wait-in-mbox_send_message-for-blocking-tx-mode.patch b/queue-3.18/mailbox-always-wait-in-mbox_send_message-for-blocking-tx-mode.patch
new file mode 100644 (file)
index 0000000..d617846
--- /dev/null
@@ -0,0 +1,40 @@
+From c61b781ee084e69855477d23dd33e7e6caad652c Mon Sep 17 00:00:00 2001
+From: Sudeep Holla <sudeep.holla@arm.com>
+Date: Tue, 21 Mar 2017 11:30:14 +0000
+Subject: mailbox: always wait in mbox_send_message for blocking Tx mode
+
+From: Sudeep Holla <sudeep.holla@arm.com>
+
+commit c61b781ee084e69855477d23dd33e7e6caad652c upstream.
+
+There exists a race when msg_submit return immediately as there was an
+active request being processed which may have completed just before it's
+checked again in mbox_send_message. This will result in return to the
+caller without waiting in mbox_send_message even when it's blocking Tx.
+
+This patch fixes the issue by waiting for the completion always if Tx
+is in blocking mode.
+
+Fixes: 2b6d83e2b8b7 ("mailbox: Introduce framework for mailbox")
+Reported-by: Alexey Klimov <alexey.klimov@arm.com>
+Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
+Reviewed-by: Alexey Klimov <alexey.klimov@arm.com>
+Signed-off-by: Jassi Brar <jaswinder.singh@linaro.org>
+Signed-off-by: Amit Pundir <amit.pundir@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/mailbox/mailbox.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/mailbox/mailbox.c
++++ b/drivers/mailbox/mailbox.c
+@@ -255,7 +255,7 @@ int mbox_send_message(struct mbox_chan *
+       if (chan->txdone_method == TXDONE_BY_POLL)
+               poll_txdone((unsigned long)chan->mbox);
+-      if (chan->cl->tx_block && chan->active_req) {
++      if (chan->cl->tx_block) {
+               unsigned long wait;
+               int ret;
diff --git a/queue-3.18/mailbox-handle-empty-message-in-tx_tick.patch b/queue-3.18/mailbox-handle-empty-message-in-tx_tick.patch
new file mode 100644 (file)
index 0000000..c4204e5
--- /dev/null
@@ -0,0 +1,40 @@
+From cb710ab1d8a23f68ff8f45aedf3e552bb90e70de Mon Sep 17 00:00:00 2001
+From: Sudeep Holla <sudeep.holla@arm.com>
+Date: Tue, 21 Mar 2017 11:30:16 +0000
+Subject: mailbox: handle empty message in tx_tick
+
+From: Sudeep Holla <sudeep.holla@arm.com>
+
+commit cb710ab1d8a23f68ff8f45aedf3e552bb90e70de upstream.
+
+We already check if the message is empty before calling the client
+tx_done callback. Calling completion on a wait event is also invalid
+if the message is empty.
+
+This patch moves the existing empty message check earlier.
+
+Fixes: 2b6d83e2b8b7 ("mailbox: Introduce framework for mailbox")
+Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
+Signed-off-by: Jassi Brar <jaswinder.singh@linaro.org>
+Signed-off-by: Amit Pundir <amit.pundir@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/mailbox/mailbox.c |    5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+--- a/drivers/mailbox/mailbox.c
++++ b/drivers/mailbox/mailbox.c
+@@ -99,8 +99,11 @@ static void tx_tick(struct mbox_chan *ch
+       /* Submit next message */
+       msg_submit(chan);
++      if (!mssg)
++              return;
++
+       /* Notify the client */
+-      if (mssg && chan->cl->tx_done)
++      if (chan->cl->tx_done)
+               chan->cl->tx_done(chan->cl, mssg, r);
+       if (r != -ETIME && chan->cl->tx_block)
diff --git a/queue-3.18/mailbox-skip-complete-wait-event-if-timer-expired.patch b/queue-3.18/mailbox-skip-complete-wait-event-if-timer-expired.patch
new file mode 100644 (file)
index 0000000..9448731
--- /dev/null
@@ -0,0 +1,53 @@
+From cc6eeaa3029a6dbcb4ad41b1f92876483bd88965 Mon Sep 17 00:00:00 2001
+From: Sudeep Holla <sudeep.holla@arm.com>
+Date: Tue, 21 Mar 2017 11:30:15 +0000
+Subject: mailbox: skip complete wait event if timer expired
+
+From: Sudeep Holla <sudeep.holla@arm.com>
+
+commit cc6eeaa3029a6dbcb4ad41b1f92876483bd88965 upstream.
+
+If a wait_for_completion_timeout() call returns due to a timeout,
+complete() can get called after returning from the wait which is
+incorrect and can cause subsequent transmissions on a channel to fail.
+Since the wait_for_completion_timeout() sees the completion variable
+is non-zero caused by the erroneous/spurious complete() call, and
+it immediately returns without waiting for the time as expected by the
+client.
+
+This patch fixes the issue by skipping complete() call for the timer
+expiry.
+
+Fixes: 2b6d83e2b8b7 ("mailbox: Introduce framework for mailbox")
+Reported-by: Alexey Klimov <alexey.klimov@arm.com>
+Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
+Signed-off-by: Jassi Brar <jaswinder.singh@linaro.org>
+Signed-off-by: Amit Pundir <amit.pundir@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/mailbox/mailbox.c |    6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+--- a/drivers/mailbox/mailbox.c
++++ b/drivers/mailbox/mailbox.c
+@@ -103,7 +103,7 @@ static void tx_tick(struct mbox_chan *ch
+       if (mssg && chan->cl->tx_done)
+               chan->cl->tx_done(chan->cl, mssg, r);
+-      if (chan->cl->tx_block)
++      if (r != -ETIME && chan->cl->tx_block)
+               complete(&chan->tx_complete);
+ }
+@@ -266,8 +266,8 @@ int mbox_send_message(struct mbox_chan *
+               ret = wait_for_completion_timeout(&chan->tx_complete, wait);
+               if (ret == 0) {
+-                      t = -EIO;
+-                      tx_tick(chan, -EIO);
++                      t = -ETIME;
++                      tx_tick(chan, t);
+               }
+       }
diff --git a/queue-3.18/mpt3sas-don-t-overreach-ioc-reply_post-during-initialization.patch b/queue-3.18/mpt3sas-don-t-overreach-ioc-reply_post-during-initialization.patch
new file mode 100644 (file)
index 0000000..2b77955
--- /dev/null
@@ -0,0 +1,120 @@
+From 5ec8a1753bc29efa7e4b1391d691c9c719b30257 Mon Sep 17 00:00:00 2001
+From: Calvin Owens <calvinowens@fb.com>
+Date: Fri, 18 Mar 2016 12:45:42 -0700
+Subject: mpt3sas: Don't overreach ioc->reply_post[] during initialization
+
+From: Calvin Owens <calvinowens@fb.com>
+
+commit 5ec8a1753bc29efa7e4b1391d691c9c719b30257 upstream.
+
+In _base_make_ioc_operational(), we walk ioc->reply_queue_list and pull
+a pointer out of successive elements of ioc->reply_post[] for each entry
+in that list if RDPQ is enabled.
+
+Since the code pulls the pointer for the next iteration at the bottom of
+the loop, it triggers the a KASAN dump on the final iteration:
+
+    BUG: KASAN: slab-out-of-bounds in _base_make_ioc_operational+0x47b7/0x47e0 [mpt3sas] at addr ffff880754816ab0
+    Read of size 8 by task modprobe/305
+    <snip>
+    Call Trace:
+     [<ffffffff81dfc591>] dump_stack+0x4d/0x6c
+     [<ffffffff814c9689>] print_trailer+0xf9/0x150
+     [<ffffffff814ceda4>] object_err+0x34/0x40
+     [<ffffffff814d1231>] kasan_report_error+0x221/0x530
+     [<ffffffff814d1673>] __asan_report_load8_noabort+0x43/0x50
+     [<ffffffffa0043637>] _base_make_ioc_operational+0x47b7/0x47e0 [mpt3sas]
+     [<ffffffffa0049a51>] mpt3sas_base_attach+0x1991/0x2120 [mpt3sas]
+     [<ffffffffa0053c93>] _scsih_probe+0xeb3/0x16b0 [mpt3sas]
+     [<ffffffff81ebd047>] local_pci_probe+0xc7/0x170
+     [<ffffffff81ebf2cf>] pci_device_probe+0x20f/0x290
+     [<ffffffff820d50cd>] really_probe+0x17d/0x600
+     [<ffffffff820d56a3>] __driver_attach+0x153/0x190
+     [<ffffffff820cffac>] bus_for_each_dev+0x11c/0x1a0
+     [<ffffffff820d421d>] driver_attach+0x3d/0x50
+     [<ffffffff820d378a>] bus_add_driver+0x44a/0x5f0
+     [<ffffffff820d666c>] driver_register+0x18c/0x3b0
+     [<ffffffff81ebcb76>] __pci_register_driver+0x156/0x200
+     [<ffffffffa00c8135>] _mpt3sas_init+0x135/0x1000 [mpt3sas]
+     [<ffffffff81000423>] do_one_initcall+0x113/0x2b0
+     [<ffffffff813caa5a>] do_init_module+0x1d0/0x4d8
+     [<ffffffff81273909>] load_module+0x6729/0x8dc0
+     [<ffffffff81276123>] SYSC_init_module+0x183/0x1a0
+     [<ffffffff8127625e>] SyS_init_module+0xe/0x10
+     [<ffffffff828fe7d7>] entry_SYSCALL_64_fastpath+0x12/0x6a
+
+Fix this by pulling the value at the beginning of the loop.
+
+Signed-off-by: Calvin Owens <calvinowens@fb.com>
+Reviewed-by: Johannes Thumshirn <jthumshirn@suse.de>
+Reviewed-by: Jens Axboe <axboe@fb.com>
+Acked-by: Chaitra Basappa <chaitra.basappa@broadcom.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Amit Pundir <amit.pundir@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/scsi/mpt3sas/mpt3sas_base.c |   33 ++++++++++++++++-----------------
+ 1 file changed, 16 insertions(+), 17 deletions(-)
+
+--- a/drivers/scsi/mpt3sas/mpt3sas_base.c
++++ b/drivers/scsi/mpt3sas/mpt3sas_base.c
+@@ -4378,14 +4378,13 @@ _base_make_ioc_ready(struct MPT3SAS_ADAP
+ static int
+ _base_make_ioc_operational(struct MPT3SAS_ADAPTER *ioc, int sleep_flag)
+ {
+-      int r, i;
++      int r, i, index;
+       unsigned long   flags;
+       u32 reply_address;
+       u16 smid;
+       struct _tr_list *delayed_tr, *delayed_tr_next;
+       struct adapter_reply_queue *reply_q;
+-      long reply_post_free;
+-      u32 reply_post_free_sz, index = 0;
++      Mpi2ReplyDescriptorsUnion_t *reply_post_free_contig;
+       dinitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name,
+           __func__));
+@@ -4456,27 +4455,27 @@ _base_make_ioc_operational(struct MPT3SA
+               _base_assign_reply_queues(ioc);
+       /* initialize Reply Post Free Queue */
+-      reply_post_free_sz = ioc->reply_post_queue_depth *
+-          sizeof(Mpi2DefaultReplyDescriptor_t);
+-      reply_post_free = (long)ioc->reply_post[index].reply_post_free;
++      index = 0;
++      reply_post_free_contig = ioc->reply_post[0].reply_post_free;
+       list_for_each_entry(reply_q, &ioc->reply_queue_list, list) {
++              /*
++               * If RDPQ is enabled, switch to the next allocation.
++               * Otherwise advance within the contiguous region.
++               */
++              if (ioc->rdpq_array_enable) {
++                      reply_q->reply_post_free =
++                              ioc->reply_post[index++].reply_post_free;
++              } else {
++                      reply_q->reply_post_free = reply_post_free_contig;
++                      reply_post_free_contig += ioc->reply_post_queue_depth;
++              }
++
+               reply_q->reply_post_host_index = 0;
+-              reply_q->reply_post_free = (Mpi2ReplyDescriptorsUnion_t *)
+-                  reply_post_free;
+               for (i = 0; i < ioc->reply_post_queue_depth; i++)
+                       reply_q->reply_post_free[i].Words =
+                           cpu_to_le64(ULLONG_MAX);
+               if (!_base_is_controller_msix_enabled(ioc))
+                       goto skip_init_reply_post_free_queue;
+-              /*
+-               * If RDPQ is enabled, switch to the next allocation.
+-               * Otherwise advance within the contiguous region.
+-               */
+-              if (ioc->rdpq_array_enable)
+-                      reply_post_free = (long)
+-                          ioc->reply_post[++index].reply_post_free;
+-              else
+-                      reply_post_free += reply_post_free_sz;
+       }
+  skip_init_reply_post_free_queue:
diff --git a/queue-3.18/net-sched-fix-soft-lockup-in-tc_classify.patch b/queue-3.18/net-sched-fix-soft-lockup-in-tc_classify.patch
new file mode 100644 (file)
index 0000000..f4f8260
--- /dev/null
@@ -0,0 +1,82 @@
+From 628185cfddf1dfb701c4efe2cfd72cf5b09f5702 Mon Sep 17 00:00:00 2001
+From: Daniel Borkmann <daniel@iogearbox.net>
+Date: Wed, 21 Dec 2016 18:04:11 +0100
+Subject: net, sched: fix soft lockup in tc_classify
+
+From: Daniel Borkmann <daniel@iogearbox.net>
+
+commit 628185cfddf1dfb701c4efe2cfd72cf5b09f5702 upstream.
+
+Shahar reported a soft lockup in tc_classify(), where we run into an
+endless loop when walking the classifier chain due to tp->next == tp
+which is a state we should never run into. The issue only seems to
+trigger under load in the tc control path.
+
+What happens is that in tc_ctl_tfilter(), thread A allocates a new
+tp, initializes it, sets tp_created to 1, and calls into tp->ops->change()
+with it. In that classifier callback we had to unlock/lock the rtnl
+mutex and returned with -EAGAIN. One reason why we need to drop there
+is, for example, that we need to request an action module to be loaded.
+
+This happens via tcf_exts_validate() -> tcf_action_init/_1() meaning
+after we loaded and found the requested action, we need to redo the
+whole request so we don't race against others. While we had to unlock
+rtnl in that time, thread B's request was processed next on that CPU.
+Thread B added a new tp instance successfully to the classifier chain.
+When thread A returned grabbing the rtnl mutex again, propagating -EAGAIN
+and destroying its tp instance which never got linked, we goto replay
+and redo A's request.
+
+This time when walking the classifier chain in tc_ctl_tfilter() for
+checking for existing tp instances we had a priority match and found
+the tp instance that was created and linked by thread B. Now calling
+again into tp->ops->change() with that tp was successful and returned
+without error.
+
+tp_created was never cleared in the second round, thus kernel thinks
+that we need to link it into the classifier chain (once again). tp and
+*back point to the same object due to the match we had earlier on. Thus
+for thread B's already public tp, we reset tp->next to tp itself and
+link it into the chain, which eventually causes the mentioned endless
+loop in tc_classify() once a packet hits the data path.
+
+Fix is to clear tp_created at the beginning of each request, also when
+we replay it. On the paths that can cause -EAGAIN we already destroy
+the original tp instance we had and on replay we really need to start
+from scratch. It seems that this issue was first introduced in commit
+12186be7d2e1 ("net_cls: fix unconfigured struct tcf_proto keeps chaining
+and avoid kernel panic when we use cls_cgroup").
+
+Fixes: 12186be7d2e1 ("net_cls: fix unconfigured struct tcf_proto keeps chaining and avoid kernel panic when we use cls_cgroup")
+Reported-by: Shahar Klein <shahark@mellanox.com>
+Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
+Cc: Cong Wang <xiyou.wangcong@gmail.com>
+Acked-by: Eric Dumazet <edumazet@google.com>
+Tested-by: Shahar Klein <shahark@mellanox.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Amit Pundir <amit.pundir@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ net/sched/cls_api.c |    4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/net/sched/cls_api.c
++++ b/net/sched/cls_api.c
+@@ -137,13 +137,15 @@ static int tc_ctl_tfilter(struct sk_buff
+       unsigned long cl;
+       unsigned long fh;
+       int err;
+-      int tp_created = 0;
++      int tp_created;
+       if ((n->nlmsg_type != RTM_GETTFILTER) &&
+           !netlink_ns_capable(skb, net->user_ns, CAP_NET_ADMIN))
+               return -EPERM;
+ replay:
++      tp_created = 0;
++
+       err = nlmsg_parse(n, sizeof(*t), tca, TCA_MAX, NULL);
+       if (err < 0)
+               return err;
diff --git a/queue-3.18/net-sctp-fix-race-for-one-to-many-sockets-in-sendmsg-s-auto-associate.patch b/queue-3.18/net-sctp-fix-race-for-one-to-many-sockets-in-sendmsg-s-auto-associate.patch
new file mode 100644 (file)
index 0000000..19ed416
--- /dev/null
@@ -0,0 +1,118 @@
+From 2061dcd6bff8b774b4fac8b0739b6be3f87bc9f2 Mon Sep 17 00:00:00 2001
+From: Daniel Borkmann <dborkman@redhat.com>
+Date: Thu, 15 Jan 2015 16:34:35 +0100
+Subject: net: sctp: fix race for one-to-many sockets in sendmsg's auto associate
+
+From: Daniel Borkmann <dborkman@redhat.com>
+
+commit 2061dcd6bff8b774b4fac8b0739b6be3f87bc9f2 upstream.
+
+I.e. one-to-many sockets in SCTP are not required to explicitly
+call into connect(2) or sctp_connectx(2) prior to data exchange.
+Instead, they can directly invoke sendmsg(2) and the SCTP stack
+will automatically trigger connection establishment through 4WHS
+via sctp_primitive_ASSOCIATE(). However, this in its current
+implementation is racy: INIT is being sent out immediately (as
+it cannot be bundled anyway) and the rest of the DATA chunks are
+queued up for later xmit when connection is established, meaning
+sendmsg(2) will return successfully. This behaviour can result
+in an undesired side-effect that the kernel made the application
+think the data has already been transmitted, although none of it
+has actually left the machine, worst case even after close(2)'ing
+the socket.
+
+Instead, when the association from client side has been shut down
+e.g. first gracefully through SCTP_EOF and then close(2), the
+client could afterwards still receive the server's INIT_ACK due
+to a connection with higher latency. This INIT_ACK is then considered
+out of the blue and hence responded with ABORT as there was no
+alive assoc found anymore. This can be easily reproduced f.e.
+with sctp_test application from lksctp. One way to fix this race
+is to wait for the handshake to actually complete.
+
+The fix defers waiting after sctp_primitive_ASSOCIATE() and
+sctp_primitive_SEND() succeeded, so that DATA chunks cooked up
+from sctp_sendmsg() have already been placed into the output
+queue through the side-effect interpreter, and therefore can then
+be bundeled together with COOKIE_ECHO control chunks.
+
+strace from example application (shortened):
+
+socket(PF_INET, SOCK_SEQPACKET, IPPROTO_SCTP) = 3
+sendmsg(3, {msg_name(28)={sa_family=AF_INET, sin_port=htons(8888), sin_addr=inet_addr("192.168.1.115")},
+           msg_iov(1)=[{"hello", 5}], msg_controllen=0, msg_flags=0}, 0) = 5
+sendmsg(3, {msg_name(28)={sa_family=AF_INET, sin_port=htons(8888), sin_addr=inet_addr("192.168.1.115")},
+           msg_iov(1)=[{"hello", 5}], msg_controllen=0, msg_flags=0}, 0) = 5
+sendmsg(3, {msg_name(28)={sa_family=AF_INET, sin_port=htons(8888), sin_addr=inet_addr("192.168.1.115")},
+           msg_iov(1)=[{"hello", 5}], msg_controllen=0, msg_flags=0}, 0) = 5
+sendmsg(3, {msg_name(28)={sa_family=AF_INET, sin_port=htons(8888), sin_addr=inet_addr("192.168.1.115")},
+           msg_iov(1)=[{"hello", 5}], msg_controllen=0, msg_flags=0}, 0) = 5
+sendmsg(3, {msg_name(28)={sa_family=AF_INET, sin_port=htons(8888), sin_addr=inet_addr("192.168.1.115")},
+           msg_iov(0)=[], msg_controllen=48, {cmsg_len=48, cmsg_level=0x84 /* SOL_??? */, cmsg_type=, ...},
+           msg_flags=0}, 0) = 0 // graceful shutdown for SOCK_SEQPACKET via SCTP_EOF
+close(3) = 0
+
+tcpdump before patch (fooling the application):
+
+22:33:36.306142 IP 192.168.1.114.41462 > 192.168.1.115.8888: sctp (1) [INIT] [init tag: 3879023686] [rwnd: 106496] [OS: 10] [MIS: 65535] [init TSN: 3139201684]
+22:33:36.316619 IP 192.168.1.115.8888 > 192.168.1.114.41462: sctp (1) [INIT ACK] [init tag: 3345394793] [rwnd: 106496] [OS: 10] [MIS: 10] [init TSN: 3380109591]
+22:33:36.317600 IP 192.168.1.114.41462 > 192.168.1.115.8888: sctp (1) [ABORT]
+
+tcpdump after patch:
+
+14:28:58.884116 IP 192.168.1.114.35846 > 192.168.1.115.8888: sctp (1) [INIT] [init tag: 438593213] [rwnd: 106496] [OS: 10] [MIS: 65535] [init TSN: 3092969729]
+14:28:58.888414 IP 192.168.1.115.8888 > 192.168.1.114.35846: sctp (1) [INIT ACK] [init tag: 381429855] [rwnd: 106496] [OS: 10] [MIS: 10] [init TSN: 2141904492]
+14:28:58.888638 IP 192.168.1.114.35846 > 192.168.1.115.8888: sctp (1) [COOKIE ECHO] , (2) [DATA] (B)(E) [TSN: 3092969729] [...]
+14:28:58.893278 IP 192.168.1.115.8888 > 192.168.1.114.35846: sctp (1) [COOKIE ACK] , (2) [SACK] [cum ack 3092969729] [a_rwnd 106491] [#gap acks 0] [#dup tsns 0]
+14:28:58.893591 IP 192.168.1.114.35846 > 192.168.1.115.8888: sctp (1) [DATA] (B)(E) [TSN: 3092969730] [...]
+14:28:59.096963 IP 192.168.1.115.8888 > 192.168.1.114.35846: sctp (1) [SACK] [cum ack 3092969730] [a_rwnd 106496] [#gap acks 0] [#dup tsns 0]
+14:28:59.097086 IP 192.168.1.114.35846 > 192.168.1.115.8888: sctp (1) [DATA] (B)(E) [TSN: 3092969731] [...] , (2) [DATA] (B)(E) [TSN: 3092969732] [...]
+14:28:59.103218 IP 192.168.1.115.8888 > 192.168.1.114.35846: sctp (1) [SACK] [cum ack 3092969732] [a_rwnd 106486] [#gap acks 0] [#dup tsns 0]
+14:28:59.103330 IP 192.168.1.114.35846 > 192.168.1.115.8888: sctp (1) [SHUTDOWN]
+14:28:59.107793 IP 192.168.1.115.8888 > 192.168.1.114.35846: sctp (1) [SHUTDOWN ACK]
+14:28:59.107890 IP 192.168.1.114.35846 > 192.168.1.115.8888: sctp (1) [SHUTDOWN COMPLETE]
+
+Looks like this bug is from the pre-git history museum. ;)
+
+Fixes: 08707d5482df ("lksctp-2_5_31-0_5_1.patch")
+Signed-off-by: Daniel Borkmann <dborkman@redhat.com>
+Acked-by: Vlad Yasevich <vyasevich@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Amit Pundir <amit.pundir@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ net/sctp/socket.c |    8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+--- a/net/sctp/socket.c
++++ b/net/sctp/socket.c
+@@ -1604,7 +1604,7 @@ static int sctp_sendmsg(struct kiocb *io
+       sctp_assoc_t associd = 0;
+       sctp_cmsgs_t cmsgs = { NULL };
+       sctp_scope_t scope;
+-      bool fill_sinfo_ttl = false;
++      bool fill_sinfo_ttl = false, wait_connect = false;
+       struct sctp_datamsg *datamsg;
+       int msg_flags = msg->msg_flags;
+       __u16 sinfo_flags = 0;
+@@ -1944,6 +1944,7 @@ static int sctp_sendmsg(struct kiocb *io
+               if (err < 0)
+                       goto out_free;
++              wait_connect = true;
+               pr_debug("%s: we associated primitively\n", __func__);
+       }
+@@ -1981,6 +1982,11 @@ static int sctp_sendmsg(struct kiocb *io
+       sctp_datamsg_put(datamsg);
+       err = msg_len;
++      if (unlikely(wait_connect)) {
++              timeo = sock_sndtimeo(sk, msg_flags & MSG_DONTWAIT);
++              sctp_wait_for_connect(asoc, &timeo);
++      }
++
+       /* If we are already past ASSOCIATE, the lower
+        * layers are responsible for association cleanup.
+        */
index 70bef1cdebdef59552156accce5347a2fdc13ee8..a1595501a4258abe8d890debcabc0176959864d7 100644 (file)
@@ -13,3 +13,19 @@ bluetooth-bnep-bnep_add_connection-should-verify-that-it-s-dealing-with-l2cap-so
 bluetooth-fix-potential-null-dereference.patch
 bluetooth-cmtp-cmtp_add_connection-should-verify-that-it-s-dealing-with-l2cap-socket.patch
 net-phy-do-not-perform-software-reset-for-generic-phy.patch
+isdn-fix-a-sleep-in-atomic-bug.patch
+string-provide-strscpy.patch
+strscpy-zero-any-trailing-garbage-bytes-in-the-destination.patch
+isdn-i4l-fix-buffer-overflow.patch
+wil6210-fix-deadlock-when-using-fw_no_recovery-option.patch
+mailbox-always-wait-in-mbox_send_message-for-blocking-tx-mode.patch
+mailbox-skip-complete-wait-event-if-timer-expired.patch
+mailbox-handle-empty-message-in-tx_tick.patch
+mpt3sas-don-t-overreach-ioc-reply_post-during-initialization.patch
+kaweth-fix-firmware-download.patch
+kaweth-fix-oops-upon-failed-memory-allocation.patch
+ipv6-fix-possible-deadlock-in-ip6_fl_purge-ip6_fl_gc.patch
+net-sctp-fix-race-for-one-to-many-sockets-in-sendmsg-s-auto-associate.patch
+sh_eth-fix-ethtool-operation-crash-when-net-device-is-down.patch
+net-sched-fix-soft-lockup-in-tc_classify.patch
+ipmi-watchdog-fix-watchdog-timeout-set-on-reboot.patch
diff --git a/queue-3.18/sh_eth-fix-ethtool-operation-crash-when-net-device-is-down.patch b/queue-3.18/sh_eth-fix-ethtool-operation-crash-when-net-device-is-down.patch
new file mode 100644 (file)
index 0000000..c5a2a0f
--- /dev/null
@@ -0,0 +1,71 @@
+From 4f9dce230b32eec45cec8c28cae61efdfa2f7d57 Mon Sep 17 00:00:00 2001
+From: Ben Hutchings <ben.hutchings@codethink.co.uk>
+Date: Fri, 16 Jan 2015 17:51:25 +0000
+Subject: sh_eth: Fix ethtool operation crash when net device is down
+
+From: Ben Hutchings <ben.hutchings@codethink.co.uk>
+
+commit 4f9dce230b32eec45cec8c28cae61efdfa2f7d57 upstream.
+
+The driver connects and disconnects the PHY device whenever the
+net device is brought up and down.  The ethtool get_settings,
+set_settings and nway_reset operations will dereference a null
+or dangling pointer if called while it is down.
+
+I think it would be preferable to keep the PHY connected, but there
+may be good reasons not to.
+
+As an immediate fix for this bug:
+- Set the phydev pointer to NULL after disconnecting the PHY
+- Change those three operations to return -ENODEV while the PHY is
+  not connected
+
+Signed-off-by: Ben Hutchings <ben.hutchings@codethink.co.uk>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Amit Pundir <amit.pundir@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/net/ethernet/renesas/sh_eth.c |   10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+--- a/drivers/net/ethernet/renesas/sh_eth.c
++++ b/drivers/net/ethernet/renesas/sh_eth.c
+@@ -1832,6 +1832,9 @@ static int sh_eth_get_settings(struct ne
+       unsigned long flags;
+       int ret;
++      if (!mdp->phydev)
++              return -ENODEV;
++
+       spin_lock_irqsave(&mdp->lock, flags);
+       ret = phy_ethtool_gset(mdp->phydev, ecmd);
+       spin_unlock_irqrestore(&mdp->lock, flags);
+@@ -1846,6 +1849,9 @@ static int sh_eth_set_settings(struct ne
+       unsigned long flags;
+       int ret;
++      if (!mdp->phydev)
++              return -ENODEV;
++
+       spin_lock_irqsave(&mdp->lock, flags);
+       /* disable tx and rx */
+@@ -1880,6 +1886,9 @@ static int sh_eth_nway_reset(struct net_
+       unsigned long flags;
+       int ret;
++      if (!mdp->phydev)
++              return -ENODEV;
++
+       spin_lock_irqsave(&mdp->lock, flags);
+       ret = phy_start_aneg(mdp->phydev);
+       spin_unlock_irqrestore(&mdp->lock, flags);
+@@ -2189,6 +2198,7 @@ static int sh_eth_close(struct net_devic
+       if (mdp->phydev) {
+               phy_stop(mdp->phydev);
+               phy_disconnect(mdp->phydev);
++              mdp->phydev = NULL;
+       }
+       free_irq(ndev->irq, ndev);
diff --git a/queue-3.18/string-provide-strscpy.patch b/queue-3.18/string-provide-strscpy.patch
new file mode 100644 (file)
index 0000000..d5136d7
--- /dev/null
@@ -0,0 +1,158 @@
+From 30035e45753b708e7d47a98398500ca005e02b86 Mon Sep 17 00:00:00 2001
+From: Chris Metcalf <cmetcalf@ezchip.com>
+Date: Wed, 29 Apr 2015 12:52:04 -0400
+Subject: string: provide strscpy()
+
+From: Chris Metcalf <cmetcalf@ezchip.com>
+
+commit 30035e45753b708e7d47a98398500ca005e02b86 upstream.
+
+The strscpy() API is intended to be used instead of strlcpy(),
+and instead of most uses of strncpy().
+
+- Unlike strlcpy(), it doesn't read from memory beyond (src + size).
+
+- Unlike strlcpy() or strncpy(), the API provides an easy way to check
+  for destination buffer overflow: an -E2BIG error return value.
+
+- The provided implementation is robust in the face of the source
+  buffer being asynchronously changed during the copy, unlike the
+  current implementation of strlcpy().
+
+- Unlike strncpy(), the destination buffer will be NUL-terminated
+  if the string in the source buffer is too long.
+
+- Also unlike strncpy(), the destination buffer will not be updated
+  beyond the NUL termination, avoiding strncpy's behavior of zeroing
+  the entire tail end of the destination buffer.  (A memset() after
+  the strscpy() can be used if this behavior is desired.)
+
+- The implementation should be reasonably performant on all
+  platforms since it uses the asm/word-at-a-time.h API rather than
+  simple byte copy.  Kernel-to-kernel string copy is not considered
+  to be performance critical in any case.
+
+Signed-off-by: Chris Metcalf <cmetcalf@ezchip.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ include/linux/string.h |    3 +
+ lib/string.c           |   88 +++++++++++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 91 insertions(+)
+
+--- a/include/linux/string.h
++++ b/include/linux/string.h
+@@ -25,6 +25,9 @@ extern char * strncpy(char *,const char
+ #ifndef __HAVE_ARCH_STRLCPY
+ size_t strlcpy(char *, const char *, size_t);
+ #endif
++#ifndef __HAVE_ARCH_STRSCPY
++ssize_t __must_check strscpy(char *, const char *, size_t);
++#endif
+ #ifndef __HAVE_ARCH_STRCAT
+ extern char * strcat(char *, const char *);
+ #endif
+--- a/lib/string.c
++++ b/lib/string.c
+@@ -27,6 +27,10 @@
+ #include <linux/bug.h>
+ #include <linux/errno.h>
++#include <asm/byteorder.h>
++#include <asm/word-at-a-time.h>
++#include <asm/page.h>
++
+ #ifndef __HAVE_ARCH_STRNCASECMP
+ /**
+  * strncasecmp - Case insensitive, length-limited string comparison
+@@ -154,6 +158,90 @@ size_t strlcpy(char *dest, const char *s
+ EXPORT_SYMBOL(strlcpy);
+ #endif
++#ifndef __HAVE_ARCH_STRSCPY
++/**
++ * strscpy - Copy a C-string into a sized buffer
++ * @dest: Where to copy the string to
++ * @src: Where to copy the string from
++ * @count: Size of destination buffer
++ *
++ * Copy the string, or as much of it as fits, into the dest buffer.
++ * The routine returns the number of characters copied (not including
++ * the trailing NUL) or -E2BIG if the destination buffer wasn't big enough.
++ * The behavior is undefined if the string buffers overlap.
++ * The destination buffer is always NUL terminated, unless it's zero-sized.
++ *
++ * Preferred to strlcpy() since the API doesn't require reading memory
++ * from the src string beyond the specified "count" bytes, and since
++ * the return value is easier to error-check than strlcpy()'s.
++ * In addition, the implementation is robust to the string changing out
++ * from underneath it, unlike the current strlcpy() implementation.
++ *
++ * Preferred to strncpy() since it always returns a valid string, and
++ * doesn't unnecessarily force the tail of the destination buffer to be
++ * zeroed.  If the zeroing is desired, it's likely cleaner to use strscpy()
++ * with an overflow test, then just memset() the tail of the dest buffer.
++ */
++ssize_t strscpy(char *dest, const char *src, size_t count)
++{
++      const struct word_at_a_time constants = WORD_AT_A_TIME_CONSTANTS;
++      size_t max = count;
++      long res = 0;
++
++      if (count == 0)
++              return -E2BIG;
++
++#ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
++      /*
++       * If src is unaligned, don't cross a page boundary,
++       * since we don't know if the next page is mapped.
++       */
++      if ((long)src & (sizeof(long) - 1)) {
++              size_t limit = PAGE_SIZE - ((long)src & (PAGE_SIZE - 1));
++              if (limit < max)
++                      max = limit;
++      }
++#else
++      /* If src or dest is unaligned, don't do word-at-a-time. */
++      if (((long) dest | (long) src) & (sizeof(long) - 1))
++              max = 0;
++#endif
++
++      while (max >= sizeof(unsigned long)) {
++              unsigned long c, data;
++
++              c = *(unsigned long *)(src+res);
++              *(unsigned long *)(dest+res) = c;
++              if (has_zero(c, &data, &constants)) {
++                      data = prep_zero_mask(c, data, &constants);
++                      data = create_zero_mask(data);
++                      return res + find_zero(data);
++              }
++              res += sizeof(unsigned long);
++              count -= sizeof(unsigned long);
++              max -= sizeof(unsigned long);
++      }
++
++      while (count) {
++              char c;
++
++              c = src[res];
++              dest[res] = c;
++              if (!c)
++                      return res;
++              res++;
++              count--;
++      }
++
++      /* Hit buffer length without finding a NUL; force NUL-termination. */
++      if (res)
++              dest[res-1] = '\0';
++
++      return -E2BIG;
++}
++EXPORT_SYMBOL(strscpy);
++#endif
++
+ #ifndef __HAVE_ARCH_STRCAT
+ /**
+  * strcat - Append one %NUL-terminated string to another
diff --git a/queue-3.18/strscpy-zero-any-trailing-garbage-bytes-in-the-destination.patch b/queue-3.18/strscpy-zero-any-trailing-garbage-bytes-in-the-destination.patch
new file mode 100644 (file)
index 0000000..1e8ba00
--- /dev/null
@@ -0,0 +1,37 @@
+From 990486c8af044f89bddfbde1d1cf9fde449bedbf Mon Sep 17 00:00:00 2001
+From: Chris Metcalf <cmetcalf@ezchip.com>
+Date: Tue, 6 Oct 2015 12:37:41 -0400
+Subject: strscpy: zero any trailing garbage bytes in the destination
+
+From: Chris Metcalf <cmetcalf@ezchip.com>
+
+commit 990486c8af044f89bddfbde1d1cf9fde449bedbf upstream.
+
+It's possible that the destination can be shadowed in userspace
+(as, for example, the perf buffers are now).  So we should take
+care not to leak data that could be inspected by userspace.
+
+Signed-off-by: Chris Metcalf <cmetcalf@ezchip.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ lib/string.c |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/lib/string.c
++++ b/lib/string.c
+@@ -211,12 +211,13 @@ ssize_t strscpy(char *dest, const char *
+               unsigned long c, data;
+               c = *(unsigned long *)(src+res);
+-              *(unsigned long *)(dest+res) = c;
+               if (has_zero(c, &data, &constants)) {
+                       data = prep_zero_mask(c, data, &constants);
+                       data = create_zero_mask(data);
++                      *(unsigned long *)(dest+res) = c & zero_bytemask(data);
+                       return res + find_zero(data);
+               }
++              *(unsigned long *)(dest+res) = c;
+               res += sizeof(unsigned long);
+               count -= sizeof(unsigned long);
+               max -= sizeof(unsigned long);
diff --git a/queue-3.18/wil6210-fix-deadlock-when-using-fw_no_recovery-option.patch b/queue-3.18/wil6210-fix-deadlock-when-using-fw_no_recovery-option.patch
new file mode 100644 (file)
index 0000000..379d12f
--- /dev/null
@@ -0,0 +1,53 @@
+From dfb5b098e0f40b68aa07f2ec55f4dd762efefbfa Mon Sep 17 00:00:00 2001
+From: Lior David <qca_liord@qca.qualcomm.com>
+Date: Wed, 23 Nov 2016 16:06:41 +0200
+Subject: wil6210: fix deadlock when using fw_no_recovery option
+
+From: Lior David <qca_liord@qca.qualcomm.com>
+
+commit dfb5b098e0f40b68aa07f2ec55f4dd762efefbfa upstream.
+
+When FW crashes with no_fw_recovery option, driver
+waits for manual recovery with wil->mutex held, this
+can easily create deadlocks.
+Fix the problem by moving the wait outside the lock.
+
+Signed-off-by: Lior David <qca_liord@qca.qualcomm.com>
+Signed-off-by: Maya Erez <qca_merez@qca.qualcomm.com>
+Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
+Signed-off-by: Amit Pundir <amit.pundir@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/net/wireless/ath/wil6210/main.c |   15 ++++++++-------
+ 1 file changed, 8 insertions(+), 7 deletions(-)
+
+--- a/drivers/net/wireless/ath/wil6210/main.c
++++ b/drivers/net/wireless/ath/wil6210/main.c
+@@ -240,18 +240,19 @@ static void wil_fw_error_worker(struct w
+       wil->last_fw_recovery = jiffies;
++      wil_info(wil, "fw error recovery requested (try %d)...\n",
++               wil->recovery_count);
++      if (!no_fw_recovery)
++              wil->recovery_state = fw_recovery_running;
++      if (wil_wait_for_recovery(wil) != 0)
++              return;
++
+       mutex_lock(&wil->mutex);
+       switch (wdev->iftype) {
+       case NL80211_IFTYPE_STATION:
+       case NL80211_IFTYPE_P2P_CLIENT:
+       case NL80211_IFTYPE_MONITOR:
+-              wil_info(wil, "fw error recovery requested (try %d)...\n",
+-                       wil->recovery_count);
+-              if (!no_fw_recovery)
+-                      wil->recovery_state = fw_recovery_running;
+-              if (0 != wil_wait_for_recovery(wil))
+-                      break;
+-
++              /* silent recovery, upper layers will see disconnect */
+               __wil_down(wil);
+               __wil_up(wil);
+               break;