From: Greg Kroah-Hartman Date: Fri, 17 Apr 2015 12:39:31 +0000 (+0200) Subject: 3.14-stable patches X-Git-Tag: v3.10.75~10 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=8c05ef2155782da0a8fc39b9f2db3c54ba03ebfa;p=thirdparty%2Fkernel%2Fstable-queue.git 3.14-stable patches 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 --- 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 index 00000000000..46a709e5600 --- /dev/null +++ b/queue-3.14/cifs-fix-use-after-free-bug-in-find_writable_file.patch @@ -0,0 +1,79 @@ +From e1e9bda22d7ddf88515e8fe401887e313922823e Mon Sep 17 00:00:00 2001 +From: David Disseldorp +Date: Fri, 13 Mar 2015 14:20:29 +0100 +Subject: cifs: fix use-after-free bug in find_writable_file + +From: David Disseldorp + +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 +Reviewed-by: Jeff Layton +Signed-off-by: Steve French +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..d405bcae9ff --- /dev/null +++ b/queue-3.14/cifs-smb2_clone_range-exit-on-unhandled-error.patch @@ -0,0 +1,38 @@ +From 2477bc58d49edb1c0baf59df7dc093dce682af2b Mon Sep 17 00:00:00 2001 +From: Sachin Prabhu +Date: Wed, 4 Feb 2015 13:10:26 +0000 +Subject: cifs: smb2_clone_range() - exit on unhandled error + +From: Sachin Prabhu + +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 +Signed-off-by: Steve French +Signed-off-by: Steve French +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..4f68c846d24 --- /dev/null +++ b/queue-3.14/n_tty-fix-read-buffer-overwrite-when-no-newline.patch @@ -0,0 +1,221 @@ +From fb5ef9e7da39968fec6d6f37f20a23d23740c75e Mon Sep 17 00:00:00 2001 +From: Peter Hurley +Date: Fri, 16 Jan 2015 15:05:39 -0500 +Subject: n_tty: Fix read buffer overwrite when no newline + +From: Peter Hurley + +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 +Signed-off-by: Greg Kroah-Hartman +(backported from commit fb5ef9e7da39968fec6d6f37f20a23d23740c75e) +Signed-off-by: Joseph Salisbury +--- + 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; diff --git a/queue-3.14/series b/queue-3.14/series index c0dd61d506c..2f9a4232086 100644 --- a/queue-3.14/series +++ b/queue-3.14/series @@ -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 index 00000000000..96731178459 --- /dev/null +++ b/queue-3.14/tty-serial-fsl_lpuart-clear-receive-flag-on-fifo-flush.patch @@ -0,0 +1,43 @@ +From 8e4934c6d6c659e22b1b746af4196683e77ce6ca Mon Sep 17 00:00:00 2001 +From: Stefan Agner +Date: Fri, 13 Mar 2015 14:51:51 +0100 +Subject: tty: serial: fsl_lpuart: clear receive flag on FIFO flush + +From: Stefan Agner + +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 +Signed-off-by: Greg Kroah-Hartman + +--- + 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);