From 83c307ca772198e72f596c924fb4eb44ba3eb745 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 15 May 2020 10:56:28 +0200 Subject: [PATCH] 4.9-stable patches 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 --- ...sg-add-sg_remove_request-in-sg_write.patch | 39 ++++++ queue-4.9/series | 2 + ...pi-rx-tx-to-prevent-concurrent-calls.patch | 129 ++++++++++++++++++ 3 files changed, 170 insertions(+) create mode 100644 queue-4.9/scsi-sg-add-sg_remove_request-in-sg_write.patch create mode 100644 queue-4.9/spi-spi-dw-add-lock-protect-dw_spi-rx-tx-to-prevent-concurrent-calls.patch 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 index 00000000000..211a046fd4e --- /dev/null +++ b/queue-4.9/scsi-sg-add-sg_remove_request-in-sg_write.patch @@ -0,0 +1,39 @@ +From 83c6f2390040f188cc25b270b4befeb5628c1aee Mon Sep 17 00:00:00 2001 +From: Wu Bo +Date: Tue, 14 Apr 2020 10:13:28 +0800 +Subject: scsi: sg: add sg_remove_request in sg_write + +From: Wu Bo + +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 +Signed-off-by: Wu Bo +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +[groeck: Backport to v5.4.y and older kernels] +Signed-off-by: Guenter Roeck +Signed-off-by: Greg Kroah-Hartman + +--- + 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 diff --git a/queue-4.9/series b/queue-4.9/series index dcdcda0ec14..6ee98306209 100644 --- a/queue-4.9/series +++ b/queue-4.9/series @@ -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 index 00000000000..a6b361a019d --- /dev/null +++ b/queue-4.9/spi-spi-dw-add-lock-protect-dw_spi-rx-tx-to-prevent-concurrent-calls.patch @@ -0,0 +1,129 @@ +From 19b61392c5a852b4e8a0bf35aecb969983c5932d Mon Sep 17 00:00:00 2001 +From: "wuxu.wu" +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 + +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 +Link: https://lore.kernel.org/r/1577849981-31489-1-git-send-email-wuxu.wu@huawei.com +Signed-off-by: Mark Brown +Signed-off-by: Nobuhiro Iwamatsu (CIP) +Signed-off-by: Greg Kroah-Hartman + +--- + 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; -- 2.47.3