]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.14-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 27 Jun 2014 22:30:25 +0000 (15:30 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 27 Jun 2014 22:30:25 +0000 (15:30 -0700)
added patches:
usb-sierra-fix-aa-deadlock-in-open-error-path.patch
usb-sierra-fix-remote-wakeup.patch
usb-sierra-fix-urb-and-memory-leak-in-resume-error-path.patch
usb-sierra-fix-urb-and-memory-leak-on-disconnect.patch
usb-sierra-fix-use-after-free-at-suspend-resume.patch

queue-3.14/series
queue-3.14/usb-sierra-fix-aa-deadlock-in-open-error-path.patch [new file with mode: 0644]
queue-3.14/usb-sierra-fix-remote-wakeup.patch [new file with mode: 0644]
queue-3.14/usb-sierra-fix-urb-and-memory-leak-in-resume-error-path.patch [new file with mode: 0644]
queue-3.14/usb-sierra-fix-urb-and-memory-leak-on-disconnect.patch [new file with mode: 0644]
queue-3.14/usb-sierra-fix-use-after-free-at-suspend-resume.patch [new file with mode: 0644]

index 8f6ad0d513b81d500d123599cfcdb5a147fc966a..2cba8f4399441897c9458d53b36f832361c88721 100644 (file)
@@ -44,3 +44,8 @@ usb-usb_wwan-fix-write-and-suspend-race.patch
 usb-usb_wwan-fix-urb-leak-at-shutdown.patch
 usb-usb_wwan-fix-potential-null-deref-at-resume.patch
 usb-usb_wwan-fix-potential-blocked-i-o-after-resume.patch
+usb-sierra-fix-aa-deadlock-in-open-error-path.patch
+usb-sierra-fix-use-after-free-at-suspend-resume.patch
+usb-sierra-fix-urb-and-memory-leak-in-resume-error-path.patch
+usb-sierra-fix-urb-and-memory-leak-on-disconnect.patch
+usb-sierra-fix-remote-wakeup.patch
diff --git a/queue-3.14/usb-sierra-fix-aa-deadlock-in-open-error-path.patch b/queue-3.14/usb-sierra-fix-aa-deadlock-in-open-error-path.patch
new file mode 100644 (file)
index 0000000..bb2fc62
--- /dev/null
@@ -0,0 +1,58 @@
+From 353fe198602e8b4d1c7bdcceb8e60955087201b1 Mon Sep 17 00:00:00 2001
+From: Johan Hovold <jhovold@gmail.com>
+Date: Mon, 26 May 2014 19:22:50 +0200
+Subject: USB: sierra: fix AA deadlock in open error path
+
+From: Johan Hovold <jhovold@gmail.com>
+
+commit 353fe198602e8b4d1c7bdcceb8e60955087201b1 upstream.
+
+Fix AA deadlock in open error path that would call close() and try to
+grab the already held disc_mutex.
+
+Fixes: b9a44bc19f48 ("sierra: driver urb handling improvements")
+
+Signed-off-by: Johan Hovold <jhovold@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/serial/sierra.c |   21 +++++++++++++--------
+ 1 file changed, 13 insertions(+), 8 deletions(-)
+
+--- a/drivers/usb/serial/sierra.c
++++ b/drivers/usb/serial/sierra.c
+@@ -816,14 +816,9 @@ static int sierra_open(struct tty_struct
+                       usb_sndbulkpipe(serial->dev, endpoint) | USB_DIR_IN);
+       err = sierra_submit_rx_urbs(port, GFP_KERNEL);
+-      if (err) {
+-              /* get rid of everything as in close */
+-              sierra_close(port);
+-              /* restore balance for autopm */
+-              if (!serial->disconnected)
+-                      usb_autopm_put_interface(serial->interface);
+-              return err;
+-      }
++      if (err)
++              goto err_submit;
++
+       sierra_send_setup(port);
+       serial->interface->needs_remote_wakeup = 1;
+@@ -833,6 +828,16 @@ static int sierra_open(struct tty_struct
+       usb_autopm_put_interface(serial->interface);
+       return 0;
++
++err_submit:
++      sierra_stop_rx_urbs(port);
++
++      for (i = 0; i < portdata->num_in_urbs; i++) {
++              sierra_release_urb(portdata->in_urbs[i]);
++              portdata->in_urbs[i] = NULL;
++      }
++
++      return err;
+ }
diff --git a/queue-3.14/usb-sierra-fix-remote-wakeup.patch b/queue-3.14/usb-sierra-fix-remote-wakeup.patch
new file mode 100644 (file)
index 0000000..dac31e1
--- /dev/null
@@ -0,0 +1,69 @@
+From 80cc0fcbdaeaf10d04ba27779a2d7ceb73d2717a Mon Sep 17 00:00:00 2001
+From: Johan Hovold <jhovold@gmail.com>
+Date: Mon, 26 May 2014 19:22:54 +0200
+Subject: USB: sierra: fix remote wakeup
+
+From: Johan Hovold <jhovold@gmail.com>
+
+commit 80cc0fcbdaeaf10d04ba27779a2d7ceb73d2717a upstream.
+
+Make sure that needs_remote_wake up is always set when there are open
+ports.
+
+Currently close() would unconditionally set needs_remote_wakeup to 0
+even though there might still be open ports. This could lead to blocked
+input and possibly dropped data on devices that do not support remote
+wakeup (and which must therefore not be runtime suspended while open).
+
+Add an open_ports counter (protected by the susp_lock) and only clear
+needs_remote_wakeup when the last port is closed.
+
+Fixes: e6929a9020ac ("USB: support for autosuspend in sierra while
+online")
+
+Signed-off-by: Johan Hovold <jhovold@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/serial/sierra.c |    7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+--- a/drivers/usb/serial/sierra.c
++++ b/drivers/usb/serial/sierra.c
+@@ -58,6 +58,7 @@ struct sierra_intf_private {
+       spinlock_t susp_lock;
+       unsigned int suspended:1;
+       int in_flight;
++      unsigned int open_ports;
+ };
+ static int sierra_set_power_state(struct usb_device *udev, __u16 swiState)
+@@ -768,7 +769,6 @@ static void sierra_close(struct usb_seri
+       mutex_lock(&serial->disc_mutex);
+       if (!serial->disconnected) {
+-              serial->interface->needs_remote_wakeup = 0;
+               /* odd error handling due to pm counters */
+               if (!usb_autopm_get_interface(serial->interface))
+                       sierra_send_setup(port);
+@@ -779,6 +779,8 @@ static void sierra_close(struct usb_seri
+       mutex_unlock(&serial->disc_mutex);
+       spin_lock_irq(&intfdata->susp_lock);
+       portdata->opened = 0;
++      if (--intfdata->open_ports == 0)
++              serial->interface->needs_remote_wakeup = 0;
+       spin_unlock_irq(&intfdata->susp_lock);
+       for (;;) {
+@@ -834,9 +836,10 @@ static int sierra_open(struct tty_struct
+       sierra_send_setup(port);
+-      serial->interface->needs_remote_wakeup = 1;
+       spin_lock_irq(&intfdata->susp_lock);
+       portdata->opened = 1;
++      if (++intfdata->open_ports == 1)
++              serial->interface->needs_remote_wakeup = 1;
+       spin_unlock_irq(&intfdata->susp_lock);
+       usb_autopm_put_interface(serial->interface);
diff --git a/queue-3.14/usb-sierra-fix-urb-and-memory-leak-in-resume-error-path.patch b/queue-3.14/usb-sierra-fix-urb-and-memory-leak-in-resume-error-path.patch
new file mode 100644 (file)
index 0000000..6a37abe
--- /dev/null
@@ -0,0 +1,49 @@
+From 7fdd26a01eb7b6cb6855ff8f69ef4a720720dfcb Mon Sep 17 00:00:00 2001
+From: Johan Hovold <jhovold@gmail.com>
+Date: Mon, 26 May 2014 19:22:52 +0200
+Subject: USB: sierra: fix urb and memory leak in resume error path
+
+From: Johan Hovold <jhovold@gmail.com>
+
+commit 7fdd26a01eb7b6cb6855ff8f69ef4a720720dfcb upstream.
+
+Neither the transfer buffer or the urb itself were released in the
+resume error path for delayed writes. Also on errors, the remainder of
+the queue was not even processed, which leads to further urb and buffer
+leaks.
+
+The same error path also failed to balance the outstanding-urb counter,
+something which results in degraded throughput or completely blocked
+writes.
+
+Fix this by releasing urb and buffer and balancing counters on errors,
+and by always processing the whole queue even when submission of one urb
+fails.
+
+Fixes: e6929a9020ac ("USB: support for autosuspend in sierra while
+online")
+
+Signed-off-by: Johan Hovold <jhovold@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/serial/sierra.c |    8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+--- a/drivers/usb/serial/sierra.c
++++ b/drivers/usb/serial/sierra.c
+@@ -1004,8 +1004,12 @@ static int sierra_resume(struct usb_seri
+                       if (err < 0) {
+                               intfdata->in_flight--;
+                               usb_unanchor_urb(urb);
+-                              usb_scuttle_anchored_urbs(&portdata->delayed);
+-                              break;
++                              kfree(urb->transfer_buffer);
++                              usb_free_urb(urb);
++                              spin_lock(&portdata->lock);
++                              portdata->outstanding_urbs--;
++                              spin_unlock(&portdata->lock);
++                              continue;
+                       }
+               }
diff --git a/queue-3.14/usb-sierra-fix-urb-and-memory-leak-on-disconnect.patch b/queue-3.14/usb-sierra-fix-urb-and-memory-leak-on-disconnect.patch
new file mode 100644 (file)
index 0000000..eae9cdc
--- /dev/null
@@ -0,0 +1,52 @@
+From 014333f77c0b71123d6ef7d31a9724e0699c9548 Mon Sep 17 00:00:00 2001
+From: Johan Hovold <jhovold@gmail.com>
+Date: Mon, 26 May 2014 19:22:53 +0200
+Subject: USB: sierra: fix urb and memory leak on disconnect
+
+From: Johan Hovold <jhovold@gmail.com>
+
+commit 014333f77c0b71123d6ef7d31a9724e0699c9548 upstream.
+
+The delayed-write queue was never emptied on disconnect, something which
+would lead to leaked urbs and transfer buffers if the device is
+disconnected before being runtime resumed due to a write.
+
+Fixes: e6929a9020ac ("USB: support for autosuspend in sierra while
+online")
+
+Signed-off-by: Johan Hovold <jhovold@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/serial/sierra.c |   13 +++++++++++++
+ 1 file changed, 13 insertions(+)
+
+--- a/drivers/usb/serial/sierra.c
++++ b/drivers/usb/serial/sierra.c
+@@ -759,6 +759,7 @@ static void sierra_close(struct usb_seri
+       struct usb_serial *serial = port->serial;
+       struct sierra_port_private *portdata;
+       struct sierra_intf_private *intfdata = port->serial->private;
++      struct urb *urb;
+       portdata = usb_get_serial_port_data(port);
+@@ -780,6 +781,18 @@ static void sierra_close(struct usb_seri
+       portdata->opened = 0;
+       spin_unlock_irq(&intfdata->susp_lock);
++      for (;;) {
++              urb = usb_get_from_anchor(&portdata->delayed);
++              if (!urb)
++                      break;
++              kfree(urb->transfer_buffer);
++              usb_free_urb(urb);
++              usb_autopm_put_interface_async(serial->interface);
++              spin_lock(&portdata->lock);
++              portdata->outstanding_urbs--;
++              spin_unlock(&portdata->lock);
++      }
++
+       sierra_stop_rx_urbs(port);
+       for (i = 0; i < portdata->num_in_urbs; i++) {
+               sierra_release_urb(portdata->in_urbs[i]);
diff --git a/queue-3.14/usb-sierra-fix-use-after-free-at-suspend-resume.patch b/queue-3.14/usb-sierra-fix-use-after-free-at-suspend-resume.patch
new file mode 100644 (file)
index 0000000..af2d359
--- /dev/null
@@ -0,0 +1,55 @@
+From 8452727de70f6ad850cd6d0aaa18b5d9050aa63b Mon Sep 17 00:00:00 2001
+From: Johan Hovold <jhovold@gmail.com>
+Date: Mon, 26 May 2014 19:22:51 +0200
+Subject: USB: sierra: fix use after free at suspend/resume
+
+From: Johan Hovold <jhovold@gmail.com>
+
+commit 8452727de70f6ad850cd6d0aaa18b5d9050aa63b upstream.
+
+Fix use after free or NULL-pointer dereference during suspend and
+resume.
+
+The port data may never have been allocated (port probe failed)
+or may already have been released by port_remove (e.g. driver is
+unloaded) when suspend and resume are called.
+
+Fixes: e6929a9020ac ("USB: support for autosuspend in sierra while
+online")
+
+Signed-off-by: Johan Hovold <jhovold@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/serial/sierra.c |    6 ++++++
+ 1 file changed, 6 insertions(+)
+
+--- a/drivers/usb/serial/sierra.c
++++ b/drivers/usb/serial/sierra.c
+@@ -933,6 +933,7 @@ static int sierra_port_remove(struct usb
+       struct sierra_port_private *portdata;
+       portdata = usb_get_serial_port_data(port);
++      usb_set_serial_port_data(port, NULL);
+       kfree(portdata);
+       return 0;
+@@ -949,6 +950,8 @@ static void stop_read_write_urbs(struct
+       for (i = 0; i < serial->num_ports; ++i) {
+               port = serial->port[i];
+               portdata = usb_get_serial_port_data(port);
++              if (!portdata)
++                      continue;
+               sierra_stop_rx_urbs(port);
+               usb_kill_anchored_urbs(&portdata->active);
+       }
+@@ -991,6 +994,9 @@ static int sierra_resume(struct usb_seri
+               port = serial->port[i];
+               portdata = usb_get_serial_port_data(port);
++              if (!portdata)
++                      continue;
++
+               while ((urb = usb_get_from_anchor(&portdata->delayed))) {
+                       usb_anchor_urb(urb, &portdata->active);
+                       intfdata->in_flight++;