]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.9-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 15 May 2020 08:56:28 +0000 (10:56 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 15 May 2020 08:56:28 +0000 (10:56 +0200)
added patches:
scsi-sg-add-sg_remove_request-in-sg_write.patch
spi-spi-dw-add-lock-protect-dw_spi-rx-tx-to-prevent-concurrent-calls.patch

queue-4.9/scsi-sg-add-sg_remove_request-in-sg_write.patch [new file with mode: 0644]
queue-4.9/series
queue-4.9/spi-spi-dw-add-lock-protect-dw_spi-rx-tx-to-prevent-concurrent-calls.patch [new file with mode: 0644]

diff --git a/queue-4.9/scsi-sg-add-sg_remove_request-in-sg_write.patch b/queue-4.9/scsi-sg-add-sg_remove_request-in-sg_write.patch
new file mode 100644 (file)
index 0000000..211a046
--- /dev/null
@@ -0,0 +1,39 @@
+From 83c6f2390040f188cc25b270b4befeb5628c1aee Mon Sep 17 00:00:00 2001
+From: Wu Bo <wubo40@huawei.com>
+Date: Tue, 14 Apr 2020 10:13:28 +0800
+Subject: scsi: sg: add sg_remove_request in sg_write
+
+From: Wu Bo <wubo40@huawei.com>
+
+commit 83c6f2390040f188cc25b270b4befeb5628c1aee upstream.
+
+If the __copy_from_user function failed we need to call sg_remove_request
+in sg_write.
+
+Link: https://lore.kernel.org/r/610618d9-e983-fd56-ed0f-639428343af7@huawei.com
+Acked-by: Douglas Gilbert <dgilbert@interlog.com>
+Signed-off-by: Wu Bo <wubo40@huawei.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+[groeck: Backport to v5.4.y and older kernels]
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/scsi/sg.c |    4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/drivers/scsi/sg.c
++++ b/drivers/scsi/sg.c
+@@ -695,8 +695,10 @@ sg_write(struct file *filp, const char _
+       hp->flags = input_size; /* structure abuse ... */
+       hp->pack_id = old_hdr.pack_id;
+       hp->usr_ptr = NULL;
+-      if (__copy_from_user(cmnd, buf, cmd_size))
++      if (__copy_from_user(cmnd, buf, cmd_size)) {
++              sg_remove_request(sfp, srp);
+               return -EFAULT;
++      }
+       /*
+        * SG_DXFER_TO_FROM_DEV is functionally equivalent to SG_DXFER_FROM_DEV,
+        * but is is possible that the app intended SG_DXFER_TO_DEV, because there
index dcdcda0ec143b3ca47f9e2aa32cdab9184102c9d..6ee983062096e38bc97af78a51f0166ee3e961b1 100644 (file)
@@ -42,3 +42,5 @@ shmem-fix-possible-deadlocks-on-shmlock_user_lock.patch
 net-sonic-fix-a-resource-leak-in-an-error-handling-p.patch
 net-moxa-fix-a-potential-double-free_irq.patch
 drop_monitor-work-around-gcc-10-stringop-overflow-wa.patch
+scsi-sg-add-sg_remove_request-in-sg_write.patch
+spi-spi-dw-add-lock-protect-dw_spi-rx-tx-to-prevent-concurrent-calls.patch
diff --git a/queue-4.9/spi-spi-dw-add-lock-protect-dw_spi-rx-tx-to-prevent-concurrent-calls.patch b/queue-4.9/spi-spi-dw-add-lock-protect-dw_spi-rx-tx-to-prevent-concurrent-calls.patch
new file mode 100644 (file)
index 0000000..a6b361a
--- /dev/null
@@ -0,0 +1,129 @@
+From 19b61392c5a852b4e8a0bf35aecb969983c5932d Mon Sep 17 00:00:00 2001
+From: "wuxu.wu" <wuxu.wu@huawei.com>
+Date: Wed, 1 Jan 2020 11:39:41 +0800
+Subject: spi: spi-dw: Add lock protect dw_spi rx/tx to prevent concurrent calls
+
+From: wuxu.wu <wuxu.wu@huawei.com>
+
+commit 19b61392c5a852b4e8a0bf35aecb969983c5932d upstream.
+
+dw_spi_irq() and dw_spi_transfer_one concurrent calls.
+
+I find a panic in dw_writer(): txw = *(u8 *)(dws->tx), when dw->tx==null,
+dw->len==4, and dw->tx_end==1.
+
+When tpm driver's message overtime dw_spi_irq() and dw_spi_transfer_one
+may concurrent visit dw_spi, so I think dw_spi structure lack of protection.
+
+Otherwise dw_spi_transfer_one set dw rx/tx buffer and then open irq,
+store dw rx/tx instructions and other cores handle irq load dw rx/tx
+instructions may out of order.
+
+       [ 1025.321302] Call trace:
+       ...
+       [ 1025.321319]  __crash_kexec+0x98/0x148
+       [ 1025.321323]  panic+0x17c/0x314
+       [ 1025.321329]  die+0x29c/0x2e8
+       [ 1025.321334]  die_kernel_fault+0x68/0x78
+       [ 1025.321337]  __do_kernel_fault+0x90/0xb0
+       [ 1025.321346]  do_page_fault+0x88/0x500
+       [ 1025.321347]  do_translation_fault+0xa8/0xb8
+       [ 1025.321349]  do_mem_abort+0x68/0x118
+       [ 1025.321351]  el1_da+0x20/0x8c
+       [ 1025.321362]  dw_writer+0xc8/0xd0
+       [ 1025.321364]  interrupt_transfer+0x60/0x110
+       [ 1025.321365]  dw_spi_irq+0x48/0x70
+       ...
+
+Signed-off-by: wuxu.wu <wuxu.wu@huawei.com>
+Link: https://lore.kernel.org/r/1577849981-31489-1-git-send-email-wuxu.wu@huawei.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Nobuhiro Iwamatsu (CIP) <nobuhiro1.iwamatsu@toshiba.co.jp>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/spi/spi-dw.c |   15 ++++++++++++---
+ drivers/spi/spi-dw.h |    1 +
+ 2 files changed, 13 insertions(+), 3 deletions(-)
+
+--- a/drivers/spi/spi-dw.c
++++ b/drivers/spi/spi-dw.c
+@@ -180,9 +180,11 @@ static inline u32 rx_max(struct dw_spi *
+ static void dw_writer(struct dw_spi *dws)
+ {
+-      u32 max = tx_max(dws);
++      u32 max;
+       u16 txw = 0;
++      spin_lock(&dws->buf_lock);
++      max = tx_max(dws);
+       while (max--) {
+               /* Set the tx word if the transfer's original "tx" is not null */
+               if (dws->tx_end - dws->len) {
+@@ -194,13 +196,16 @@ static void dw_writer(struct dw_spi *dws
+               dw_write_io_reg(dws, DW_SPI_DR, txw);
+               dws->tx += dws->n_bytes;
+       }
++      spin_unlock(&dws->buf_lock);
+ }
+ static void dw_reader(struct dw_spi *dws)
+ {
+-      u32 max = rx_max(dws);
++      u32 max;
+       u16 rxw;
++      spin_lock(&dws->buf_lock);
++      max = rx_max(dws);
+       while (max--) {
+               rxw = dw_read_io_reg(dws, DW_SPI_DR);
+               /* Care rx only if the transfer's original "rx" is not null */
+@@ -212,6 +217,7 @@ static void dw_reader(struct dw_spi *dws
+               }
+               dws->rx += dws->n_bytes;
+       }
++      spin_unlock(&dws->buf_lock);
+ }
+ static void int_error_stop(struct dw_spi *dws, const char *msg)
+@@ -284,18 +290,20 @@ static int dw_spi_transfer_one(struct sp
+ {
+       struct dw_spi *dws = spi_master_get_devdata(master);
+       struct chip_data *chip = spi_get_ctldata(spi);
++      unsigned long flags;
+       u8 imask = 0;
+       u16 txlevel = 0;
+       u32 cr0;
+       int ret;
+       dws->dma_mapped = 0;
+-
++      spin_lock_irqsave(&dws->buf_lock, flags);
+       dws->tx = (void *)transfer->tx_buf;
+       dws->tx_end = dws->tx + transfer->len;
+       dws->rx = transfer->rx_buf;
+       dws->rx_end = dws->rx + transfer->len;
+       dws->len = transfer->len;
++      spin_unlock_irqrestore(&dws->buf_lock, flags);
+       spi_enable_chip(dws, 0);
+@@ -487,6 +495,7 @@ int dw_spi_add_host(struct device *dev,
+       dws->dma_inited = 0;
+       dws->dma_addr = (dma_addr_t)(dws->paddr + DW_SPI_DR);
+       snprintf(dws->name, sizeof(dws->name), "dw_spi%d", dws->bus_num);
++      spin_lock_init(&dws->buf_lock);
+       ret = request_irq(dws->irq, dw_spi_irq, IRQF_SHARED, dws->name, master);
+       if (ret < 0) {
+--- a/drivers/spi/spi-dw.h
++++ b/drivers/spi/spi-dw.h
+@@ -117,6 +117,7 @@ struct dw_spi {
+       size_t                  len;
+       void                    *tx;
+       void                    *tx_end;
++      spinlock_t              buf_lock;
+       void                    *rx;
+       void                    *rx_end;
+       int                     dma_mapped;