]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.4-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 27 Jun 2014 22:30:41 +0000 (15:30 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 27 Jun 2014 22:30:41 +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.4/series
queue-3.4/usb-sierra-fix-aa-deadlock-in-open-error-path.patch [new file with mode: 0644]
queue-3.4/usb-sierra-fix-remote-wakeup.patch [new file with mode: 0644]
queue-3.4/usb-sierra-fix-urb-and-memory-leak-in-resume-error-path.patch [new file with mode: 0644]
queue-3.4/usb-sierra-fix-urb-and-memory-leak-on-disconnect.patch [new file with mode: 0644]
queue-3.4/usb-sierra-fix-use-after-free-at-suspend-resume.patch [new file with mode: 0644]

index 254a5a70b6605e5e3f87afafa49c2c6cba2e8737..ce1f7a596ebf8b0997af19857d6bef32f036b502 100644 (file)
@@ -21,3 +21,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.4/usb-sierra-fix-aa-deadlock-in-open-error-path.patch b/queue-3.4/usb-sierra-fix-aa-deadlock-in-open-error-path.patch
new file mode 100644 (file)
index 0000000..0f67fb6
--- /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
+@@ -867,14 +867,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;
+@@ -884,6 +879,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.4/usb-sierra-fix-remote-wakeup.patch b/queue-3.4/usb-sierra-fix-remote-wakeup.patch
new file mode 100644 (file)
index 0000000..aa10b6b
--- /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
+@@ -59,6 +59,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)
+@@ -813,7 +814,6 @@ static void sierra_close(struct usb_seri
+       if (serial->dev) {
+               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);
+@@ -824,6 +824,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 (;;) {
+@@ -884,9 +886,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.4/usb-sierra-fix-urb-and-memory-leak-in-resume-error-path.patch b/queue-3.4/usb-sierra-fix-urb-and-memory-leak-in-resume-error-path.patch
new file mode 100644 (file)
index 0000000..8f33376
--- /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
+@@ -1070,8 +1070,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.4/usb-sierra-fix-urb-and-memory-leak-on-disconnect.patch b/queue-3.4/usb-sierra-fix-urb-and-memory-leak-on-disconnect.patch
new file mode 100644 (file)
index 0000000..4c44cc0
--- /dev/null
@@ -0,0 +1,51 @@
+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 |   12 ++++++++++++
+ 1 file changed, 12 insertions(+)
+
+--- a/drivers/usb/serial/sierra.c
++++ b/drivers/usb/serial/sierra.c
+@@ -801,6 +801,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;
+       dev_dbg(&port->dev, "%s\n", __func__);
+@@ -825,6 +826,17 @@ 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);
++              }
+               /* Stop reading urbs */
+               sierra_stop_rx_urbs(port);
diff --git a/queue-3.4/usb-sierra-fix-use-after-free-at-suspend-resume.patch b/queue-3.4/usb-sierra-fix-use-after-free-at-suspend-resume.patch
new file mode 100644 (file)
index 0000000..d544866
--- /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
+@@ -999,6 +999,7 @@ static void sierra_release(struct usb_se
+               portdata = usb_get_serial_port_data(port);
+               if (!portdata)
+                       continue;
++              usb_set_serial_port_data(port, NULL);
+               kfree(portdata);
+       }
+       kfree(serial->private);
+@@ -1015,6 +1016,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);
+       }
+@@ -1057,6 +1060,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++;