]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.10-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 2 Oct 2014 19:33:06 +0000 (12:33 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 2 Oct 2014 19:33:06 +0000 (12:33 -0700)
added patches:
i2c-at91-add-bound-checking-on-smbus-block-length-bytes.patch
i2c-at91-fix-a-race-condition-during-signal-handling-in-at91_do_twi_xfer.patch

queue-3.10/i2c-at91-add-bound-checking-on-smbus-block-length-bytes.patch [new file with mode: 0644]
queue-3.10/i2c-at91-fix-a-race-condition-during-signal-handling-in-at91_do_twi_xfer.patch [new file with mode: 0644]
queue-3.10/series

diff --git a/queue-3.10/i2c-at91-add-bound-checking-on-smbus-block-length-bytes.patch b/queue-3.10/i2c-at91-add-bound-checking-on-smbus-block-length-bytes.patch
new file mode 100644 (file)
index 0000000..245e799
--- /dev/null
@@ -0,0 +1,87 @@
+From 75b81f339c6af43f6f4a1b3eabe0603321dade65 Mon Sep 17 00:00:00 2001
+From: Marek Roszko <mark.roszko@gmail.com>
+Date: Wed, 20 Aug 2014 21:39:41 -0400
+Subject: i2c: at91: add bound checking on SMBus block length bytes
+
+From: Marek Roszko <mark.roszko@gmail.com>
+
+commit 75b81f339c6af43f6f4a1b3eabe0603321dade65 upstream.
+
+The driver was not bound checking the received length byte to ensure it was within the
+the buffer size that is allocated for SMBus blocks. This resulted in buffer overflows
+whenever an invalid length byte was received.
+It also failed to ensure the length byte was not zero. If it received zero, it would end up
+in an infinite loop as the at91_twi_read_next_byte function returned immediately without
+allowing RHR to be read to clear the RXRDY interrupt.
+
+Tested agaisnt a SMBus compliant battery.
+
+Signed-off-by: Marek Roszko <mark.roszko@gmail.com>
+Acked-by: Ludovic Desroches <ludovic.desroches@atmel.com>
+Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/i2c/busses/i2c-at91.c |   28 ++++++++++++++++++++++++----
+ 1 file changed, 24 insertions(+), 4 deletions(-)
+
+--- a/drivers/i2c/busses/i2c-at91.c
++++ b/drivers/i2c/busses/i2c-at91.c
+@@ -102,6 +102,7 @@ struct at91_twi_dev {
+       unsigned twi_cwgr_reg;
+       struct at91_twi_pdata *pdata;
+       bool use_dma;
++      bool recv_len_abort;
+       struct at91_twi_dma dma;
+ };
+@@ -268,12 +269,24 @@ static void at91_twi_read_next_byte(stru
+       *dev->buf = at91_twi_read(dev, AT91_TWI_RHR) & 0xff;
+       --dev->buf_len;
++      /* return if aborting, we only needed to read RHR to clear RXRDY*/
++      if (dev->recv_len_abort)
++              return;
++
+       /* handle I2C_SMBUS_BLOCK_DATA */
+       if (unlikely(dev->msg->flags & I2C_M_RECV_LEN)) {
+-              dev->msg->flags &= ~I2C_M_RECV_LEN;
+-              dev->buf_len += *dev->buf;
+-              dev->msg->len = dev->buf_len + 1;
+-              dev_dbg(dev->dev, "received block length %d\n", dev->buf_len);
++              /* ensure length byte is a valid value */
++              if (*dev->buf <= I2C_SMBUS_BLOCK_MAX && *dev->buf > 0) {
++                      dev->msg->flags &= ~I2C_M_RECV_LEN;
++                      dev->buf_len += *dev->buf;
++                      dev->msg->len = dev->buf_len + 1;
++                      dev_dbg(dev->dev, "received block length %d\n",
++                                       dev->buf_len);
++              } else {
++                      /* abort and send the stop by reading one more byte */
++                      dev->recv_len_abort = true;
++                      dev->buf_len = 1;
++              }
+       }
+       /* send stop if second but last byte has been read */
+@@ -445,6 +458,12 @@ static int at91_do_twi_transfer(struct a
+               ret = -EIO;
+               goto error;
+       }
++      if (dev->recv_len_abort) {
++              dev_err(dev->dev, "invalid smbus block length recvd\n");
++              ret = -EPROTO;
++              goto error;
++      }
++
+       dev_dbg(dev->dev, "transfer complete\n");
+       return 0;
+@@ -501,6 +520,7 @@ static int at91_twi_xfer(struct i2c_adap
+       dev->buf_len = m_start->len;
+       dev->buf = m_start->buf;
+       dev->msg = m_start;
++      dev->recv_len_abort = false;
+       ret = at91_do_twi_transfer(dev);
diff --git a/queue-3.10/i2c-at91-fix-a-race-condition-during-signal-handling-in-at91_do_twi_xfer.patch b/queue-3.10/i2c-at91-fix-a-race-condition-during-signal-handling-in-at91_do_twi_xfer.patch
new file mode 100644 (file)
index 0000000..510a904
--- /dev/null
@@ -0,0 +1,47 @@
+From 6721f28a26efd6368497abbdef5dcfc59608d899 Mon Sep 17 00:00:00 2001
+From: Simon Lindgren <simon@aqwary.com>
+Date: Tue, 26 Aug 2014 21:13:24 +0200
+Subject: i2c: at91: Fix a race condition during signal handling in at91_do_twi_xfer.
+
+From: Simon Lindgren <simon@aqwary.com>
+
+commit 6721f28a26efd6368497abbdef5dcfc59608d899 upstream.
+
+There is a race condition in at91_do_twi_xfer when signals arrive.
+If a signal is recieved while waiting for a transfer to complete
+wait_for_completion_interruptible_timeout() will return -ERESTARTSYS.
+This is not handled correctly resulting in interrupts still being
+enabled and a transfer being in flight when we return.
+
+Symptoms include a range of oopses and bus lockups. Oopses can happen
+when the transfer completes because the interrupt handler will corrupt
+the stack. If a new transfer is started before the interrupt fires
+the controller will start a new transfer in the middle of the old one,
+resulting in confused slaves and a locked bus.
+
+To avoid this, use wait_for_completion_io_timeout instead so that we
+don't have to deal with gracefully shutting down the transfer and
+disabling the interrupts.
+
+Signed-off-by: Simon Lindgren <simon@aqwary.com>
+Acked-by: Ludovic Desroches <ludovic.desroches@atmel.com>
+Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/i2c/busses/i2c-at91.c |    4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/i2c/busses/i2c-at91.c
++++ b/drivers/i2c/busses/i2c-at91.c
+@@ -435,8 +435,8 @@ static int at91_do_twi_transfer(struct a
+               }
+       }
+-      ret = wait_for_completion_interruptible_timeout(&dev->cmd_complete,
+-                                                      dev->adapter.timeout);
++      ret = wait_for_completion_io_timeout(&dev->cmd_complete,
++                                           dev->adapter.timeout);
+       if (ret == 0) {
+               dev_err(dev->dev, "controller timed out\n");
+               at91_init_twi_bus(dev);
index 0311f7947b21ffbb48243180c92753a83f3e8486..fb6761e27343592b2cae906e91997ed5accfb18d 100644 (file)
@@ -14,3 +14,5 @@ ahci-add-device-ids-for-intel-9-series-pch.patch
 ahci-add-pcid-for-marvel-0x9182-controller.patch
 ibmveth-fix-endian-issues-with-rx_no_buffer-statistic.patch
 arm64-flush-tls-registers-during-exec.patch
+i2c-at91-add-bound-checking-on-smbus-block-length-bytes.patch
+i2c-at91-fix-a-race-condition-during-signal-handling-in-at91_do_twi_xfer.patch