]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.14-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 17 Apr 2015 12:39:31 +0000 (14:39 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 17 Apr 2015 12:39:31 +0000 (14:39 +0200)
added patches:
cifs-fix-use-after-free-bug-in-find_writable_file.patch
cifs-smb2_clone_range-exit-on-unhandled-error.patch
n_tty-fix-read-buffer-overwrite-when-no-newline.patch
tty-serial-fsl_lpuart-clear-receive-flag-on-fifo-flush.patch

queue-3.14/cifs-fix-use-after-free-bug-in-find_writable_file.patch [new file with mode: 0644]
queue-3.14/cifs-smb2_clone_range-exit-on-unhandled-error.patch [new file with mode: 0644]
queue-3.14/n_tty-fix-read-buffer-overwrite-when-no-newline.patch [new file with mode: 0644]
queue-3.14/series
queue-3.14/tty-serial-fsl_lpuart-clear-receive-flag-on-fifo-flush.patch [new file with mode: 0644]

diff --git a/queue-3.14/cifs-fix-use-after-free-bug-in-find_writable_file.patch b/queue-3.14/cifs-fix-use-after-free-bug-in-find_writable_file.patch
new file mode 100644 (file)
index 0000000..46a709e
--- /dev/null
@@ -0,0 +1,79 @@
+From e1e9bda22d7ddf88515e8fe401887e313922823e Mon Sep 17 00:00:00 2001
+From: David Disseldorp <ddiss@suse.de>
+Date: Fri, 13 Mar 2015 14:20:29 +0100
+Subject: cifs: fix use-after-free bug in find_writable_file
+
+From: David Disseldorp <ddiss@suse.de>
+
+commit e1e9bda22d7ddf88515e8fe401887e313922823e upstream.
+
+Under intermittent network outages, find_writable_file() is susceptible
+to the following race condition, which results in a user-after-free in
+the cifs_writepages code-path:
+
+Thread 1                                        Thread 2
+========                                        ========
+
+inv_file = NULL
+refind = 0
+spin_lock(&cifs_file_list_lock)
+
+// invalidHandle found on openFileList
+
+inv_file = open_file
+// inv_file->count currently 1
+
+cifsFileInfo_get(inv_file)
+// inv_file->count = 2
+
+spin_unlock(&cifs_file_list_lock);
+
+cifs_reopen_file()                            cifs_close()
+// fails (rc != 0)                            ->cifsFileInfo_put()
+                                       spin_lock(&cifs_file_list_lock)
+                                       // inv_file->count = 1
+                                       spin_unlock(&cifs_file_list_lock)
+
+spin_lock(&cifs_file_list_lock);
+list_move_tail(&inv_file->flist,
+      &cifs_inode->openFileList);
+spin_unlock(&cifs_file_list_lock);
+
+cifsFileInfo_put(inv_file);
+->spin_lock(&cifs_file_list_lock)
+
+  // inv_file->count = 0
+  list_del(&cifs_file->flist);
+  // cleanup!!
+  kfree(cifs_file);
+
+  spin_unlock(&cifs_file_list_lock);
+
+spin_lock(&cifs_file_list_lock);
+++refind;
+// refind = 1
+goto refind_writable;
+
+At this point we loop back through with an invalid inv_file pointer
+and a refind value of 1. On second pass, inv_file is not overwritten on
+openFileList traversal, and is subsequently dereferenced.
+
+Signed-off-by: David Disseldorp <ddiss@suse.de>
+Reviewed-by: Jeff Layton <jlayton@samba.org>
+Signed-off-by: Steve French <smfrench@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/cifs/file.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/fs/cifs/file.c
++++ b/fs/cifs/file.c
+@@ -1821,6 +1821,7 @@ refind_writable:
+                       cifsFileInfo_put(inv_file);
+                       spin_lock(&cifs_file_list_lock);
+                       ++refind;
++                      inv_file = NULL;
+                       goto refind_writable;
+               }
+       }
diff --git a/queue-3.14/cifs-smb2_clone_range-exit-on-unhandled-error.patch b/queue-3.14/cifs-smb2_clone_range-exit-on-unhandled-error.patch
new file mode 100644 (file)
index 0000000..d405bca
--- /dev/null
@@ -0,0 +1,38 @@
+From 2477bc58d49edb1c0baf59df7dc093dce682af2b Mon Sep 17 00:00:00 2001
+From: Sachin Prabhu <sprabhu@redhat.com>
+Date: Wed, 4 Feb 2015 13:10:26 +0000
+Subject: cifs: smb2_clone_range() - exit on unhandled error
+
+From: Sachin Prabhu <sprabhu@redhat.com>
+
+commit 2477bc58d49edb1c0baf59df7dc093dce682af2b upstream.
+
+While attempting to clone a file on a samba server, we receive a
+STATUS_INVALID_DEVICE_REQUEST. This is mapped to -EOPNOTSUPP which
+isn't handled in smb2_clone_range(). We end up looping in the while loop
+making same call to the samba server over and over again.
+
+The proposed fix is to exit and return the error value when encountered
+with an unhandled error.
+
+Signed-off-by: Sachin Prabhu <sprabhu@redhat.com>
+Signed-off-by: Steve French <steve.french@primarydata.com>
+Signed-off-by: Steve French <smfrench@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/cifs/smb2ops.c |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/fs/cifs/smb2ops.c
++++ b/fs/cifs/smb2ops.c
+@@ -630,7 +630,8 @@ smb2_clone_range(const unsigned int xid,
+                       /* No need to change MaxChunks since already set to 1 */
+                       chunk_sizes_updated = true;
+-              }
++              } else
++                      goto cchunk_out;
+       }
+ cchunk_out:
diff --git a/queue-3.14/n_tty-fix-read-buffer-overwrite-when-no-newline.patch b/queue-3.14/n_tty-fix-read-buffer-overwrite-when-no-newline.patch
new file mode 100644 (file)
index 0000000..4f68c84
--- /dev/null
@@ -0,0 +1,221 @@
+From fb5ef9e7da39968fec6d6f37f20a23d23740c75e Mon Sep 17 00:00:00 2001
+From: Peter Hurley <peter@hurleysoftware.com>
+Date: Fri, 16 Jan 2015 15:05:39 -0500
+Subject: n_tty: Fix read buffer overwrite when no newline
+
+From: Peter Hurley <peter@hurleysoftware.com>
+
+commit fb5ef9e7da39968fec6d6f37f20a23d23740c75e upstream.
+
+In canon mode, the read buffer head will advance over the buffer tail
+if the input > 4095 bytes without receiving a line termination char.
+
+Discard additional input until a line termination is received.
+Before evaluating for overflow, the 'room' value is normalized for
+I_PARMRK and 1 byte is reserved for line termination (even in !icanon
+mode, in case the mode is switched). The following table shows the
+transform:
+
+ actual buffer |  'room' value before overflow calc
+  space avail  |    !I_PARMRK    |    I_PARMRK
+ --------------------------------------------------
+      0        |       -1        |       -1
+      1        |        0        |        0
+      2        |        1        |        0
+      3        |        2        |        0
+      4+       |        3        |        1
+
+When !icanon or when icanon and the read buffer contains newlines,
+normalized 'room' values of -1 and 0 are clamped to 0, and
+'overflow' is 0, so read_head is not adjusted and the input i/o loop
+exits (setting no_room if called from flush_to_ldisc()). No input
+is discarded since the reader does have input available to read
+which ensures forward progress.
+
+When icanon and the read buffer does not contain newlines and the
+normalized 'room' value is 0, then overflow and room are reset to 1,
+so that the i/o loop will process the next input char normally
+(except for parity errors which are ignored). Thus, erasures, signalling
+chars, 7-bit mode, etc. will continue to be handled properly.
+
+If the input char processed was not a line termination char, then
+the canon_head index will not have advanced, so the normalized 'room'
+value will now be -1 and 'overflow' will be set, which indicates the
+read_head can safely be reset, effectively erasing the last char
+processed.
+
+If the input char processed was a line termination, then the
+canon_head index will have advanced, so 'overflow' is cleared to 0,
+the read_head is not reset, and 'room' is cleared to 0, which exits
+the i/o loop (because the reader now have input available to read
+which ensures forward progress).
+
+Note that it is possible for a line termination to be received, and
+for the reader to copy the line to the user buffer before the
+input i/o loop is ready to process the next input char. This is
+why the i/o loop recomputes the room/overflow state with every
+input char while handling overflow.
+
+Finally, if the input data was processed without receiving
+a line termination (so that overflow is still set), the pty
+driver must receive a write wakeup. A pty writer may be waiting
+to write more data in n_tty_write() but without unthrottling
+here that wakeup will not arrive, and forward progress will halt.
+(Normally, the pty writer is woken when the reader reads data out
+of the buffer and more space become available).
+
+Signed-off-by: Peter Hurley <peter@hurleysoftware.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+(backported from commit fb5ef9e7da39968fec6d6f37f20a23d23740c75e)
+Signed-off-by: Joseph Salisbury <joseph.salisbury@canonical.com>
+---
+ drivers/tty/n_tty.c |  106 ++++++++++++++++++++++++++++++++++++++--------------
+ 1 file changed, 79 insertions(+), 27 deletions(-)
+
+--- a/drivers/tty/n_tty.c
++++ b/drivers/tty/n_tty.c
+@@ -247,8 +247,6 @@ static void n_tty_write_wakeup(struct tt
+ static void n_tty_check_throttle(struct tty_struct *tty)
+ {
+-      if (tty->driver->type == TTY_DRIVER_TYPE_PTY)
+-              return;
+       /*
+        * Check the remaining room for the input canonicalization
+        * mode.  We don't want to throttle the driver if we're in
+@@ -1512,23 +1510,6 @@ n_tty_receive_char_lnext(struct tty_stru
+               n_tty_receive_char_flagged(tty, c, flag);
+ }
+-/**
+- *    n_tty_receive_buf       -       data receive
+- *    @tty: terminal device
+- *    @cp: buffer
+- *    @fp: flag buffer
+- *    @count: characters
+- *
+- *    Called by the terminal driver when a block of characters has
+- *    been received. This function must be called from soft contexts
+- *    not from interrupt context. The driver is responsible for making
+- *    calls one at a time and in order (or using flush_to_ldisc)
+- *
+- *    n_tty_receive_buf()/producer path:
+- *            claims non-exclusive termios_rwsem
+- *            publishes read_head and canon_head
+- */
+-
+ static void
+ n_tty_receive_buf_real_raw(struct tty_struct *tty, const unsigned char *cp,
+                          char *fp, int count)
+@@ -1684,24 +1665,85 @@ static void __receive_buf(struct tty_str
+       }
+ }
++/**
++ *    n_tty_receive_buf_common        -       process input
++ *    @tty: device to receive input
++ *    @cp: input chars
++ *    @fp: flags for each char (if NULL, all chars are TTY_NORMAL)
++ *    @count: number of input chars in @cp
++ *
++ *    Called by the terminal driver when a block of characters has
++ *    been received. This function must be called from soft contexts
++ *    not from interrupt context. The driver is responsible for making
++ *    calls one at a time and in order (or using flush_to_ldisc)
++ *
++ *    Returns the # of input chars from @cp which were processed.
++ *
++ *    In canonical mode, the maximum line length is 4096 chars (including
++ *    the line termination char); lines longer than 4096 chars are
++ *    truncated. After 4095 chars, input data is still processed but
++ *    not stored. Overflow processing ensures the tty can always
++ *    receive more input until at least one line can be read.
++ *
++ *    In non-canonical mode, the read buffer will only accept 4095 chars;
++ *    this provides the necessary space for a newline char if the input
++ *    mode is switched to canonical.
++ *
++ *    Note it is possible for the read buffer to _contain_ 4096 chars
++ *    in non-canonical mode: the read buffer could already contain the
++ *    maximum canon line of 4096 chars when the mode is switched to
++ *    non-canonical.
++ *
++ *    n_tty_receive_buf()/producer path:
++ *            claims non-exclusive termios_rwsem
++ *            publishes commit_head or canon_head
++ */
+ static int
+ n_tty_receive_buf_common(struct tty_struct *tty, const unsigned char *cp,
+                        char *fp, int count, int flow)
+ {
+       struct n_tty_data *ldata = tty->disc_data;
+-      int room, n, rcvd = 0;
++      int room, n, rcvd = 0, overflow;
+       down_read(&tty->termios_rwsem);
+       while (1) {
+-              room = receive_room(tty);
++              /*
++               * When PARMRK is set, each input char may take up to 3 chars
++               * in the read buf; reduce the buffer space avail by 3x
++               *
++               * If we are doing input canonicalization, and there are no
++               * pending newlines, let characters through without limit, so
++               * that erase characters will be handled.  Other excess
++               * characters will be beeped.
++               *
++               * paired with store in *_copy_from_read_buf() -- guarantees
++               * the consumer has loaded the data in read_buf up to the new
++               * read_tail (so this producer will not overwrite unread data)
++               */
++              size_t tail = ldata->read_tail;
++
++              room = N_TTY_BUF_SIZE - (ldata->read_head - tail);
++              if (I_PARMRK(tty))
++                      room = (room + 2) / 3;
++              room--;
++              if (room <= 0) {
++                      overflow = ldata->icanon && ldata->canon_head == tail;
++                      if (overflow && room < 0)
++                              ldata->read_head--;
++                      room = overflow;
++                      ldata->no_room = flow && !room;
++              } else
++                      overflow = 0;
++
+               n = min(count, room);
+-              if (!n) {
+-                      if (flow && !room)
+-                              ldata->no_room = 1;
++              if (!n)
+                       break;
+-              }
+-              __receive_buf(tty, cp, fp, n);
++
++              /* ignore parity errors if handling overflow */
++              if (!overflow || !fp || *fp != TTY_PARITY)
++                      __receive_buf(tty, cp, fp, n);
++
+               cp += n;
+               if (fp)
+                       fp += n;
+@@ -1710,7 +1752,17 @@ n_tty_receive_buf_common(struct tty_stru
+       }
+       tty->receive_room = room;
+-      n_tty_check_throttle(tty);
++
++      /* Unthrottle if handling overflow on pty */
++      if (tty->driver->type == TTY_DRIVER_TYPE_PTY) {
++              if (overflow) {
++                      tty_set_flow_change(tty, TTY_UNTHROTTLE_SAFE);
++                      tty_unthrottle_safe(tty);
++                      __tty_set_flow_change(tty, 0);
++              }
++      } else
++              n_tty_check_throttle(tty);
++
+       up_read(&tty->termios_rwsem);
+       return rcvd;
index c0dd61d506c1e0c2b2932d06b0c43de7d9f9613b..2f9a4232086ca5e2d610c82ea836aff0b97ab4a1 100644 (file)
@@ -28,3 +28,7 @@ cpuidle-remove-state_count-field-from-struct-cpuidle_device.patch
 cpuidle-acpi-do-not-overwrite-name-and-description-of-c0.patch
 usb-xhci-handle-config-error-change-cec-in-xhci-driver.patch
 usb-xhci-apply-xhci_avoid_bei-quirk-to-all-intel-xhci-controllers.patch
+tty-serial-fsl_lpuart-clear-receive-flag-on-fifo-flush.patch
+n_tty-fix-read-buffer-overwrite-when-no-newline.patch
+cifs-smb2_clone_range-exit-on-unhandled-error.patch
+cifs-fix-use-after-free-bug-in-find_writable_file.patch
diff --git a/queue-3.14/tty-serial-fsl_lpuart-clear-receive-flag-on-fifo-flush.patch b/queue-3.14/tty-serial-fsl_lpuart-clear-receive-flag-on-fifo-flush.patch
new file mode 100644 (file)
index 0000000..9673117
--- /dev/null
@@ -0,0 +1,43 @@
+From 8e4934c6d6c659e22b1b746af4196683e77ce6ca Mon Sep 17 00:00:00 2001
+From: Stefan Agner <stefan@agner.ch>
+Date: Fri, 13 Mar 2015 14:51:51 +0100
+Subject: tty: serial: fsl_lpuart: clear receive flag on FIFO flush
+
+From: Stefan Agner <stefan@agner.ch>
+
+commit 8e4934c6d6c659e22b1b746af4196683e77ce6ca upstream.
+
+When the receiver was enabled during startup, a character could
+have been in the FIFO when the UART get initially used. The
+driver configures the (receive) watermark level, and flushes the
+FIFO. However, the receive flag (RDRF) could still be set at that
+stage (as mentioned in the register description of UARTx_RWFIFO).
+This leads to an interrupt which won't be handled properly in
+interrupt mode: The receive interrupt function lpuart_rxint checks
+the FIFO count, which is 0 at that point (due to the flush
+during initialization). The problem does not manifest when using
+DMA to receive characters.
+
+Fix this situation by explicitly read the status register, which
+leads to clearing of the RDRF flag. Due to the flush just after
+the status flag read, a explicit data read is not to required.
+
+Signed-off-by: Stefan Agner <stefan@agner.ch>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/tty/serial/fsl_lpuart.c |    3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/drivers/tty/serial/fsl_lpuart.c
++++ b/drivers/tty/serial/fsl_lpuart.c
+@@ -362,6 +362,9 @@ static void lpuart_setup_watermark(struc
+       writeb(val | UARTPFIFO_TXFE | UARTPFIFO_RXFE,
+                       sport->port.membase + UARTPFIFO);
++      /* explicitly clear RDRF */
++      readb(sport->port.membase + UARTSR1);
++
+       /* flush Tx and Rx FIFO */
+       writeb(UARTCFIFO_TXFLUSH | UARTCFIFO_RXFLUSH,
+                       sport->port.membase + UARTCFIFO);