From 0267ffce562c8bbf9b57ebe0e38445ad04972890 Mon Sep 17 00:00:00 2001 From: Qiushi Wu Date: Thu, 28 May 2020 15:13:53 -0500 Subject: scsi: iscsi: Fix reference count leak in iscsi_boot_create_kobj kobject_init_and_add() takes reference even when it fails. If this function returns an error, kobject_put() must be called to properly clean up the memory associated with the object. Link: https://lore.kernel.org/r/20200528201353.14849-1-wu000273@umn.edu Reviewed-by: Lee Duncan Signed-off-by: Qiushi Wu Signed-off-by: Martin K. Petersen --- drivers/scsi/iscsi_boot_sysfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/iscsi_boot_sysfs.c b/drivers/scsi/iscsi_boot_sysfs.c index e4857b728033..a64abe38db2d 100644 --- a/drivers/scsi/iscsi_boot_sysfs.c +++ b/drivers/scsi/iscsi_boot_sysfs.c @@ -352,7 +352,7 @@ iscsi_boot_create_kobj(struct iscsi_boot_kset *boot_kset, boot_kobj->kobj.kset = boot_kset->kset; if (kobject_init_and_add(&boot_kobj->kobj, &iscsi_boot_ktype, NULL, name, index)) { - kfree(boot_kobj); + kobject_put(&boot_kobj->kobj); return NULL; } boot_kobj->data = data; -- cgit v1.2.3 From 61e6ba03ea26f0205e535862009ff6ffdbf4de0c Mon Sep 17 00:00:00 2001 From: Suganath Prabu S Date: Thu, 28 May 2020 10:56:17 -0400 Subject: scsi: mpt3sas: Fix memset() in non-RDPQ mode Fix memset() accessing out of range address when reply_queue count is less than RDPQ_MAX_INDEX_IN_ONE_CHUNK (i.e. 16) in non-RDPQ mode. In non-RDPQ mode, the driver allocates a single contiguous pool of size reply_queue's count * reqly_post_free_sz. But the driver is always memsetting this pool with size 16 * reqly_post_free_sz. If reply queue count is less than 16 (i.e. when MSI-X vectors enabled < 16), the driver is accessing out of range address and this results in 'BUG: unable to handle kernel paging request at fff0x...x' bug. Make driver use dma_pool_zalloc() API to allocate and zero the pool. Link: https://lore.kernel.org/r/20200528145617.27252-1-suganath-prabu.subramani@broadcom.com Fixes: 8012209eb26b ("scsi: mpt3sas: Handle RDPQ DMA allocation in same 4G region") Signed-off-by: Suganath Prabu S Signed-off-by: Martin K. Petersen --- drivers/scsi/mpt3sas/mpt3sas_base.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c b/drivers/scsi/mpt3sas/mpt3sas_base.c index beaea1933f5c..96b78fdc6b8a 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.c +++ b/drivers/scsi/mpt3sas/mpt3sas_base.c @@ -4984,7 +4984,7 @@ base_alloc_rdpq_dma_pool(struct MPT3SAS_ADAPTER *ioc, int sz) for (i = 0; i < count; i++) { if ((i % RDPQ_MAX_INDEX_IN_ONE_CHUNK == 0) && dma_alloc_count) { ioc->reply_post[i].reply_post_free = - dma_pool_alloc(ioc->reply_post_free_dma_pool, + dma_pool_zalloc(ioc->reply_post_free_dma_pool, GFP_KERNEL, &ioc->reply_post[i].reply_post_free_dma); if (!ioc->reply_post[i].reply_post_free) @@ -5008,9 +5008,6 @@ base_alloc_rdpq_dma_pool(struct MPT3SAS_ADAPTER *ioc, int sz) ioc->reply_post[i].reply_post_free_dma)); return -EAGAIN; } - memset(ioc->reply_post[i].reply_post_free, 0, - RDPQ_MAX_INDEX_IN_ONE_CHUNK * - reply_post_free_sz); dma_alloc_count--; } else { -- cgit v1.2.3 From 89523cb8a67cea2642deb19042a15fdd8c4138d4 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Wed, 27 May 2020 12:52:42 +0100 Subject: scsi: qedf: Remove redundant initialization of variable rc The variable rc is being initialized with a value that is never read and it is being updated later with a new value. The initialization is redundant and can be removed. Link: https://lore.kernel.org/r/20200527115242.172344-1-colin.king@canonical.com Addresses-Coverity: ("Unused value") Signed-off-by: Colin Ian King Signed-off-by: Martin K. Petersen --- drivers/scsi/qedf/qedf_fip.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/qedf/qedf_fip.c b/drivers/scsi/qedf/qedf_fip.c index bb82f0875eca..ad6a56ce72a8 100644 --- a/drivers/scsi/qedf/qedf_fip.c +++ b/drivers/scsi/qedf/qedf_fip.c @@ -20,7 +20,7 @@ void qedf_fcoe_send_vlan_req(struct qedf_ctx *qedf) #define MY_FIP_ALL_FCF_MACS ((__u8[6]) { 1, 0x10, 0x18, 1, 0, 2 }) static u8 my_fcoe_all_fcfs[ETH_ALEN] = MY_FIP_ALL_FCF_MACS; unsigned long flags = 0; - int rc = -1; + int rc; skb = dev_alloc_skb(sizeof(struct fip_vlan)); if (!skb) { -- cgit v1.2.3 From be32acff43800c87dc5c707f5d47cc607b76b653 Mon Sep 17 00:00:00 2001 From: Can Guo Date: Wed, 27 May 2020 19:24:42 -0700 Subject: scsi: ufs: Don't update urgent bkops level when toggling auto bkops Urgent bkops level is used to compare against actual bkops status read from UFS device. Urgent bkops level is set during initialization and might be updated in exception event handler during runtime. But it should not be updated to the actual bkops status every time when auto bkops is toggled. Otherwise, if urgent bkops level is updated to 0, auto bkops shall always be kept enabled. Link: https://lore.kernel.org/r/1590632686-17866-1-git-send-email-cang@codeaurora.org Fixes: 24366c2afbb0 ("scsi: ufs: Recheck bkops level if bkops is disabled") Reviewed-by: Stanley Chu Signed-off-by: Can Guo Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufshcd.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 5db18f444ea9..2bdee9edec0d 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -5123,7 +5123,6 @@ static int ufshcd_bkops_ctrl(struct ufs_hba *hba, err = ufshcd_enable_auto_bkops(hba); else err = ufshcd_disable_auto_bkops(hba); - hba->urgent_bkops_lvl = curr_status; out: return err; } -- cgit v1.2.3 From 7b6668d8b806b013cfe084aeb72c7eebb578cb50 Mon Sep 17 00:00:00 2001 From: Stanley Chu Date: Sat, 30 May 2020 22:12:00 +0800 Subject: scsi: ufs: Remove redundant urgent_bkop_lvl initialization In ufshcd_probe_hba(), all BKOP SW tracking variables can be reset together in ufshcd_force_reset_auto_bkops(), thus urgent_bkop_lvl initialization in the beginning of ufshcd_probe_hba() can be merged into ufshcd_force_reset_auto_bkops(). Link: https://lore.kernel.org/r/20200530141200.4616-1-stanley.chu@mediatek.com Reviewed-by: Avri Altman Signed-off-by: Stanley Chu Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufshcd.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 2bdee9edec0d..ad4fc829cbb2 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -5076,6 +5076,7 @@ static void ufshcd_force_reset_auto_bkops(struct ufs_hba *hba) hba->ee_ctrl_mask &= ~MASK_EE_URGENT_BKOPS; ufshcd_disable_auto_bkops(hba); } + hba->urgent_bkops_lvl = BKOPS_STATUS_PERF_IMPACT; hba->is_urgent_bkops_lvl_checked = false; } @@ -7372,10 +7373,6 @@ static int ufshcd_probe_hba(struct ufs_hba *hba, bool async) if (ret) goto out; - /* set the default level for urgent bkops */ - hba->urgent_bkops_lvl = BKOPS_STATUS_PERF_IMPACT; - hba->is_urgent_bkops_lvl_checked = false; - /* Debug counters initialization */ ufshcd_clear_dbg_ufs_stats(hba); -- cgit v1.2.3 From 138125f74b254fd2e37b3d875faf8e0e8608299b Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 30 May 2020 00:40:25 +0100 Subject: scsi: hpsa: Lift {BIG_,}IOCTL_Command_struct copy{in,out} into hpsa_ioctl() Link: https://lore.kernel.org/r/20200529234028.46373-1-viro@ZenIV.linux.org.uk Acked-by: Don Brace Tested-by: Don Brace Signed-off-by: Al Viro Signed-off-by: Martin K. Petersen --- drivers/scsi/hpsa.c | 116 +++++++++++++++++++++++++--------------------------- 1 file changed, 56 insertions(+), 60 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 1e9302e99d05..3344a06c938e 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -6358,37 +6358,33 @@ static int hpsa_getdrivver_ioctl(struct ctlr_info *h, void __user *argp) return 0; } -static int hpsa_passthru_ioctl(struct ctlr_info *h, void __user *argp) +static int hpsa_passthru_ioctl(struct ctlr_info *h, + IOCTL_Command_struct *iocommand) { - IOCTL_Command_struct iocommand; struct CommandList *c; char *buff = NULL; u64 temp64; int rc = 0; - if (!argp) - return -EINVAL; if (!capable(CAP_SYS_RAWIO)) return -EPERM; - if (copy_from_user(&iocommand, argp, sizeof(iocommand))) - return -EFAULT; - if ((iocommand.buf_size < 1) && - (iocommand.Request.Type.Direction != XFER_NONE)) { + if ((iocommand->buf_size < 1) && + (iocommand->Request.Type.Direction != XFER_NONE)) { return -EINVAL; } - if (iocommand.buf_size > 0) { - buff = kmalloc(iocommand.buf_size, GFP_KERNEL); + if (iocommand->buf_size > 0) { + buff = kmalloc(iocommand->buf_size, GFP_KERNEL); if (buff == NULL) return -ENOMEM; - if (iocommand.Request.Type.Direction & XFER_WRITE) { + if (iocommand->Request.Type.Direction & XFER_WRITE) { /* Copy the data into the buffer we created */ - if (copy_from_user(buff, iocommand.buf, - iocommand.buf_size)) { + if (copy_from_user(buff, iocommand->buf, + iocommand->buf_size)) { rc = -EFAULT; goto out_kfree; } } else { - memset(buff, 0, iocommand.buf_size); + memset(buff, 0, iocommand->buf_size); } } c = cmd_alloc(h); @@ -6398,23 +6394,23 @@ static int hpsa_passthru_ioctl(struct ctlr_info *h, void __user *argp) c->scsi_cmd = SCSI_CMD_BUSY; /* Fill in Command Header */ c->Header.ReplyQueue = 0; /* unused in simple mode */ - if (iocommand.buf_size > 0) { /* buffer to fill */ + if (iocommand->buf_size > 0) { /* buffer to fill */ c->Header.SGList = 1; c->Header.SGTotal = cpu_to_le16(1); } else { /* no buffers to fill */ c->Header.SGList = 0; c->Header.SGTotal = cpu_to_le16(0); } - memcpy(&c->Header.LUN, &iocommand.LUN_info, sizeof(c->Header.LUN)); + memcpy(&c->Header.LUN, &iocommand->LUN_info, sizeof(c->Header.LUN)); /* Fill in Request block */ - memcpy(&c->Request, &iocommand.Request, + memcpy(&c->Request, &iocommand->Request, sizeof(c->Request)); /* Fill in the scatter gather information */ - if (iocommand.buf_size > 0) { + if (iocommand->buf_size > 0) { temp64 = dma_map_single(&h->pdev->dev, buff, - iocommand.buf_size, DMA_BIDIRECTIONAL); + iocommand->buf_size, DMA_BIDIRECTIONAL); if (dma_mapping_error(&h->pdev->dev, (dma_addr_t) temp64)) { c->SG[0].Addr = cpu_to_le64(0); c->SG[0].Len = cpu_to_le32(0); @@ -6422,12 +6418,12 @@ static int hpsa_passthru_ioctl(struct ctlr_info *h, void __user *argp) goto out; } c->SG[0].Addr = cpu_to_le64(temp64); - c->SG[0].Len = cpu_to_le32(iocommand.buf_size); + c->SG[0].Len = cpu_to_le32(iocommand->buf_size); c->SG[0].Ext = cpu_to_le32(HPSA_SG_LAST); /* not chaining */ } rc = hpsa_scsi_do_simple_cmd(h, c, DEFAULT_REPLY_QUEUE, NO_TIMEOUT); - if (iocommand.buf_size > 0) + if (iocommand->buf_size > 0) hpsa_pci_unmap(h->pdev, c, 1, DMA_BIDIRECTIONAL); check_ioctl_unit_attention(h, c); if (rc) { @@ -6436,16 +6432,12 @@ static int hpsa_passthru_ioctl(struct ctlr_info *h, void __user *argp) } /* Copy the error information out */ - memcpy(&iocommand.error_info, c->err_info, - sizeof(iocommand.error_info)); - if (copy_to_user(argp, &iocommand, sizeof(iocommand))) { - rc = -EFAULT; - goto out; - } - if ((iocommand.Request.Type.Direction & XFER_READ) && - iocommand.buf_size > 0) { + memcpy(&iocommand->error_info, c->err_info, + sizeof(iocommand->error_info)); + if ((iocommand->Request.Type.Direction & XFER_READ) && + iocommand->buf_size > 0) { /* Copy the data out of the buffer we created */ - if (copy_to_user(iocommand.buf, buff, iocommand.buf_size)) { + if (copy_to_user(iocommand->buf, buff, iocommand->buf_size)) { rc = -EFAULT; goto out; } @@ -6457,9 +6449,9 @@ out_kfree: return rc; } -static int hpsa_big_passthru_ioctl(struct ctlr_info *h, void __user *argp) +static int hpsa_big_passthru_ioctl(struct ctlr_info *h, + BIG_IOCTL_Command_struct *ioc) { - BIG_IOCTL_Command_struct *ioc; struct CommandList *c; unsigned char **buff = NULL; int *buff_size = NULL; @@ -6470,29 +6462,17 @@ static int hpsa_big_passthru_ioctl(struct ctlr_info *h, void __user *argp) u32 sz; BYTE __user *data_ptr; - if (!argp) - return -EINVAL; if (!capable(CAP_SYS_RAWIO)) return -EPERM; - ioc = vmemdup_user(argp, sizeof(*ioc)); - if (IS_ERR(ioc)) { - status = PTR_ERR(ioc); - goto cleanup1; - } + if ((ioc->buf_size < 1) && - (ioc->Request.Type.Direction != XFER_NONE)) { - status = -EINVAL; - goto cleanup1; - } + (ioc->Request.Type.Direction != XFER_NONE)) + return -EINVAL; /* Check kmalloc limits using all SGs */ - if (ioc->malloc_size > MAX_KMALLOC_SIZE) { - status = -EINVAL; - goto cleanup1; - } - if (ioc->buf_size > ioc->malloc_size * SG_ENTRIES_IN_CMD) { - status = -EINVAL; - goto cleanup1; - } + if (ioc->malloc_size > MAX_KMALLOC_SIZE) + return -EINVAL; + if (ioc->buf_size > ioc->malloc_size * SG_ENTRIES_IN_CMD) + return -EINVAL; buff = kcalloc(SG_ENTRIES_IN_CMD, sizeof(char *), GFP_KERNEL); if (!buff) { status = -ENOMEM; @@ -6565,10 +6545,6 @@ static int hpsa_big_passthru_ioctl(struct ctlr_info *h, void __user *argp) /* Copy the error information out */ memcpy(&ioc->error_info, c->err_info, sizeof(ioc->error_info)); - if (copy_to_user(argp, ioc, sizeof(*ioc))) { - status = -EFAULT; - goto cleanup0; - } if ((ioc->Request.Type.Direction & XFER_READ) && ioc->buf_size > 0) { int i; @@ -6594,7 +6570,6 @@ cleanup1: kfree(buff); } kfree(buff_size); - kvfree(ioc); return status; } @@ -6628,18 +6603,39 @@ static int hpsa_ioctl(struct scsi_device *dev, unsigned int cmd, return hpsa_getpciinfo_ioctl(h, argp); case CCISS_GETDRIVVER: return hpsa_getdrivver_ioctl(h, argp); - case CCISS_PASSTHRU: + case CCISS_PASSTHRU: { + IOCTL_Command_struct iocommand; + + if (!argp) + return -EINVAL; + if (copy_from_user(&iocommand, argp, sizeof(iocommand))) + return -EFAULT; if (atomic_dec_if_positive(&h->passthru_cmds_avail) < 0) return -EAGAIN; - rc = hpsa_passthru_ioctl(h, argp); + rc = hpsa_passthru_ioctl(h, &iocommand); atomic_inc(&h->passthru_cmds_avail); + if (!rc && copy_to_user(argp, &iocommand, sizeof(iocommand))) + rc = -EFAULT; return rc; - case CCISS_BIG_PASSTHRU: + } + case CCISS_BIG_PASSTHRU: { + BIG_IOCTL_Command_struct *ioc; + if (!argp) + return -EINVAL; if (atomic_dec_if_positive(&h->passthru_cmds_avail) < 0) return -EAGAIN; - rc = hpsa_big_passthru_ioctl(h, argp); + ioc = vmemdup_user(argp, sizeof(*ioc)); + if (IS_ERR(ioc)) { + atomic_inc(&h->passthru_cmds_avail); + return PTR_ERR(ioc); + } + rc = hpsa_big_passthru_ioctl(h, ioc); atomic_inc(&h->passthru_cmds_avail); + if (!rc && copy_to_user(argp, ioc, sizeof(*ioc))) + rc = -EFAULT; + kvfree(ioc); return rc; + } default: return -ENOTTY; } -- cgit v1.2.3 From cb17c1b69b175e3f7ae2ef53e384889cdbae5c0d Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 30 May 2020 00:40:26 +0100 Subject: scsi: hpsa: Don't bother with vmalloc for BIG_IOCTL_Command_struct "BIG" in the name refers to the amount of data being transferred, _not_ the size of structure itself; it's 140 or 144 bytes (for 32bit and 64bit hosts resp.). IOCTL_Command_struct is 136 or 144 bytes large... No point whatsoever turning that into dynamic allocation, let alone vmalloc one. Just keep it as local variable... Link: https://lore.kernel.org/r/20200529234028.46373-2-viro@ZenIV.linux.org.uk Acked-by: Don Brace Tested-by: Don Brace Signed-off-by: Al Viro Signed-off-by: Martin K. Petersen --- drivers/scsi/hpsa.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 3344a06c938e..64fd97272109 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -6619,21 +6619,17 @@ static int hpsa_ioctl(struct scsi_device *dev, unsigned int cmd, return rc; } case CCISS_BIG_PASSTHRU: { - BIG_IOCTL_Command_struct *ioc; + BIG_IOCTL_Command_struct ioc; if (!argp) return -EINVAL; + if (copy_from_user(&ioc, argp, sizeof(ioc))) + return -EFAULT; if (atomic_dec_if_positive(&h->passthru_cmds_avail) < 0) return -EAGAIN; - ioc = vmemdup_user(argp, sizeof(*ioc)); - if (IS_ERR(ioc)) { - atomic_inc(&h->passthru_cmds_avail); - return PTR_ERR(ioc); - } - rc = hpsa_big_passthru_ioctl(h, ioc); + rc = hpsa_big_passthru_ioctl(h, &ioc); atomic_inc(&h->passthru_cmds_avail); - if (!rc && copy_to_user(argp, ioc, sizeof(*ioc))) + if (!rc && copy_to_user(argp, &ioc, sizeof(ioc))) rc = -EFAULT; - kvfree(ioc); return rc; } default: -- cgit v1.2.3 From 10100ffd5f6584298b72f9fe26f32cf02abfb8b0 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 30 May 2020 00:40:27 +0100 Subject: scsi: hpsa: Get rid of compat_alloc_user_space() No need for building a native struct on kernel stack, copying it to userland one, then calling hpsa_ioctl() which copies it back into _another_ instance of the same struct. Link: https://lore.kernel.org/r/20200529234028.46373-3-viro@ZenIV.linux.org.uk Acked-by: Don Brace Tested-by: Don Brace Signed-off-by: Al Viro Signed-off-by: Martin K. Petersen --- drivers/scsi/hpsa.c | 80 ++++++++++++++++++++++++----------------------------- 1 file changed, 36 insertions(+), 44 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 64fd97272109..c7fbe56891ef 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -254,6 +254,10 @@ static irqreturn_t do_hpsa_intr_intx(int irq, void *dev_id); static irqreturn_t do_hpsa_intr_msi(int irq, void *dev_id); static int hpsa_ioctl(struct scsi_device *dev, unsigned int cmd, void __user *arg); +static int hpsa_passthru_ioctl(struct ctlr_info *h, + IOCTL_Command_struct *iocommand); +static int hpsa_big_passthru_ioctl(struct ctlr_info *h, + BIG_IOCTL_Command_struct *ioc); #ifdef CONFIG_COMPAT static int hpsa_compat_ioctl(struct scsi_device *dev, unsigned int cmd, @@ -6217,75 +6221,63 @@ static void cmd_free(struct ctlr_info *h, struct CommandList *c) static int hpsa_ioctl32_passthru(struct scsi_device *dev, unsigned int cmd, void __user *arg) { - IOCTL32_Command_struct __user *arg32 = - (IOCTL32_Command_struct __user *) arg; + struct ctlr_info *h = sdev_to_hba(dev); + IOCTL32_Command_struct __user *arg32 = arg; IOCTL_Command_struct arg64; - IOCTL_Command_struct __user *p = compat_alloc_user_space(sizeof(arg64)); int err; u32 cp; - memset(&arg64, 0, sizeof(arg64)); - err = 0; - err |= copy_from_user(&arg64.LUN_info, &arg32->LUN_info, - sizeof(arg64.LUN_info)); - err |= copy_from_user(&arg64.Request, &arg32->Request, - sizeof(arg64.Request)); - err |= copy_from_user(&arg64.error_info, &arg32->error_info, - sizeof(arg64.error_info)); - err |= get_user(arg64.buf_size, &arg32->buf_size); - err |= get_user(cp, &arg32->buf); - arg64.buf = compat_ptr(cp); - err |= copy_to_user(p, &arg64, sizeof(arg64)); + if (!arg) + return -EINVAL; - if (err) + memset(&arg64, 0, sizeof(arg64)); + if (copy_from_user(&arg64, arg32, offsetof(IOCTL_Command_struct, buf))) + return -EFAULT; + if (get_user(cp, &arg32->buf)) return -EFAULT; + arg64.buf = compat_ptr(cp); - err = hpsa_ioctl(dev, CCISS_PASSTHRU, p); + if (atomic_dec_if_positive(&h->passthru_cmds_avail) < 0) + return -EAGAIN; + err = hpsa_passthru_ioctl(h, &arg64); + atomic_inc(&h->passthru_cmds_avail); if (err) return err; - err |= copy_in_user(&arg32->error_info, &p->error_info, - sizeof(arg32->error_info)); - if (err) + if (copy_to_user(&arg32->error_info, &arg64.error_info, + sizeof(arg32->error_info))) return -EFAULT; - return err; + return 0; } static int hpsa_ioctl32_big_passthru(struct scsi_device *dev, unsigned int cmd, void __user *arg) { - BIG_IOCTL32_Command_struct __user *arg32 = - (BIG_IOCTL32_Command_struct __user *) arg; + struct ctlr_info *h = sdev_to_hba(dev); + BIG_IOCTL32_Command_struct __user *arg32 = arg; BIG_IOCTL_Command_struct arg64; - BIG_IOCTL_Command_struct __user *p = - compat_alloc_user_space(sizeof(arg64)); int err; u32 cp; + if (!arg) + return -EINVAL; memset(&arg64, 0, sizeof(arg64)); - err = 0; - err |= copy_from_user(&arg64.LUN_info, &arg32->LUN_info, - sizeof(arg64.LUN_info)); - err |= copy_from_user(&arg64.Request, &arg32->Request, - sizeof(arg64.Request)); - err |= copy_from_user(&arg64.error_info, &arg32->error_info, - sizeof(arg64.error_info)); - err |= get_user(arg64.buf_size, &arg32->buf_size); - err |= get_user(arg64.malloc_size, &arg32->malloc_size); - err |= get_user(cp, &arg32->buf); - arg64.buf = compat_ptr(cp); - err |= copy_to_user(p, &arg64, sizeof(arg64)); - - if (err) + if (copy_from_user(&arg64, arg32, + offsetof(BIG_IOCTL32_Command_struct, buf))) return -EFAULT; + if (get_user(cp, &arg32->buf)) + return -EFAULT; + arg64.buf = compat_ptr(cp); - err = hpsa_ioctl(dev, CCISS_BIG_PASSTHRU, p); + if (atomic_dec_if_positive(&h->passthru_cmds_avail) < 0) + return -EAGAIN; + err = hpsa_big_passthru_ioctl(h, &arg64); + atomic_inc(&h->passthru_cmds_avail); if (err) return err; - err |= copy_in_user(&arg32->error_info, &p->error_info, - sizeof(arg32->error_info)); - if (err) + if (copy_to_user(&arg32->error_info, &arg64.error_info, + sizeof(arg32->error_info))) return -EFAULT; - return err; + return 0; } static int hpsa_compat_ioctl(struct scsi_device *dev, unsigned int cmd, -- cgit v1.2.3 From 06b43f968db58fd582b09b745338eae5af9f9f5e Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 30 May 2020 00:40:28 +0100 Subject: scsi: hpsa: hpsa_ioctl(): Tidy up a bit Link: https://lore.kernel.org/r/20200529234028.46373-4-viro@ZenIV.linux.org.uk Acked-by: Don Brace Tested-by: Don Brace Signed-off-by: Al Viro Signed-off-by: Martin K. Petersen --- drivers/scsi/hpsa.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index c7fbe56891ef..81d0414e2117 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -6577,14 +6577,11 @@ static void check_ioctl_unit_attention(struct ctlr_info *h, * ioctl */ static int hpsa_ioctl(struct scsi_device *dev, unsigned int cmd, - void __user *arg) + void __user *argp) { - struct ctlr_info *h; - void __user *argp = (void __user *)arg; + struct ctlr_info *h = sdev_to_hba(dev); int rc; - h = sdev_to_hba(dev); - switch (cmd) { case CCISS_DEREGDISK: case CCISS_REGNEWDISK: -- cgit v1.2.3 From 08e9cbe75facfe08b9017eca37c9f1c5a6490b4a Mon Sep 17 00:00:00 2001 From: John Hubbard Date: Tue, 26 May 2020 11:27:09 -0700 Subject: scsi: st: Convert convert get_user_pages() --> pin_user_pages() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This code was using get_user_pages*(), in a "Case 1" scenario (Direct IO), using the categorization from [1]. That means that it's time to convert the get_user_pages*() + put_page() calls to pin_user_pages*() + unpin_user_pages() calls. There is some helpful background in [2]: basically, this is a small part of fixing a long-standing disconnect between pinning pages, and file systems' use of those pages. Note that this effectively changes the code's behavior as well: it now ultimately calls set_page_dirty_lock(), instead of SetPageDirty().This is probably more accurate. As Christoph Hellwig put it, "set_page_dirty() is only safe if we are dealing with a file backed page where we have reference on the inode it hangs off." [3] Also, this deletes one of the two FIXME comments (about refcounting), because there is nothing wrong with the refcounting at this point. [1] Documentation/core-api/pin_user_pages.rst [2] "Explicit pinning of user-space pages": https://lwn.net/Articles/807108/ [3] https://lore.kernel.org/r/20190723153640.GB720@lst.de Link: https://lore.kernel.org/r/20200526182709.99599-1-jhubbard@nvidia.com Cc: "Kai Mäkisara (Kolumbus)" Cc: Bart Van Assche Cc: James E.J. Bottomley Cc: Martin K. Petersen Cc: linux-scsi@vger.kernel.org Acked-by: Kai Mäkisara Signed-off-by: John Hubbard Signed-off-by: Martin K. Petersen --- drivers/scsi/st.c | 20 +++++--------------- 1 file changed, 5 insertions(+), 15 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index 4bf4ab3b70f4..87fbc0ea350b 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c @@ -4921,7 +4921,7 @@ static int sgl_map_user_pages(struct st_buffer *STbp, unsigned long end = (uaddr + count + PAGE_SIZE - 1) >> PAGE_SHIFT; unsigned long start = uaddr >> PAGE_SHIFT; const int nr_pages = end - start; - int res, i, j; + int res, i; struct page **pages; struct rq_map_data *mdata = &STbp->map_data; @@ -4943,7 +4943,7 @@ static int sgl_map_user_pages(struct st_buffer *STbp, /* Try to fault in all of the necessary pages */ /* rw==READ means read from drive, write into memory area */ - res = get_user_pages_fast(uaddr, nr_pages, rw == READ ? FOLL_WRITE : 0, + res = pin_user_pages_fast(uaddr, nr_pages, rw == READ ? FOLL_WRITE : 0, pages); /* Errors and no page mapped should return here */ @@ -4963,8 +4963,7 @@ static int sgl_map_user_pages(struct st_buffer *STbp, return nr_pages; out_unmap: if (res > 0) { - for (j=0; j < res; j++) - put_page(pages[j]); + unpin_user_pages(pages, res); res = 0; } kfree(pages); @@ -4976,18 +4975,9 @@ static int sgl_map_user_pages(struct st_buffer *STbp, static int sgl_unmap_user_pages(struct st_buffer *STbp, const unsigned int nr_pages, int dirtied) { - int i; - - for (i=0; i < nr_pages; i++) { - struct page *page = STbp->mapped_pages[i]; + /* FIXME: cache flush missing for rw==READ */ + unpin_user_pages_dirty_lock(STbp->mapped_pages, nr_pages, dirtied); - if (dirtied) - SetPageDirty(page); - /* FIXME: cache flush missing for rw==READ - * FIXME: call the correct reference counting function - */ - put_page(page); - } kfree(STbp->mapped_pages); STbp->mapped_pages = NULL; -- cgit v1.2.3 From a247e07f8dadba5da9f188aaf4f96db0302146d9 Mon Sep 17 00:00:00 2001 From: Simon Arlott Date: Sat, 30 May 2020 18:58:25 +0100 Subject: scsi: sr: Fix sr_probe() missing mutex_destroy If the device minor cannot be allocated or the cdrom fails to be registered then the mutex should be destroyed. Link: https://lore.kernel.org/r/06e9de38-eeed-1cab-5e08-e889288935b3@0882a8b5-c6c3-11e9-b005-00805fc181fe Fixes: 51a858817dcd ("scsi: sr: get rid of sr global mutex") Signed-off-by: Simon Arlott Signed-off-by: Martin K. Petersen --- drivers/scsi/sr.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/scsi') diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c index 7727893238c7..59718903e1ef 100644 --- a/drivers/scsi/sr.c +++ b/drivers/scsi/sr.c @@ -813,6 +813,7 @@ static int sr_probe(struct device *dev) fail_put: put_disk(disk); + mutex_destroy(&cd->lock); fail_free: kfree(cd); fail: -- cgit v1.2.3 From 6555781b3fdec5e94e6914511496144241df7dee Mon Sep 17 00:00:00 2001 From: Simon Arlott Date: Sat, 30 May 2020 18:59:44 +0100 Subject: scsi: sr: Fix sr_probe() missing deallocate of device minor If the cdrom fails to be registered then the device minor should be deallocated. Link: https://lore.kernel.org/r/072dac4b-8402-4de8-36bd-47e7588969cd@0882a8b5-c6c3-11e9-b005-00805fc181fe Signed-off-by: Simon Arlott Signed-off-by: Martin K. Petersen --- drivers/scsi/sr.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c index 59718903e1ef..b9cff27e2c81 100644 --- a/drivers/scsi/sr.c +++ b/drivers/scsi/sr.c @@ -793,7 +793,7 @@ static int sr_probe(struct device *dev) cd->cdi.disk = disk; if (register_cdrom(&cd->cdi)) - goto fail_put; + goto fail_minor; /* * Initialize block layer runtime PM stuffs before the @@ -811,6 +811,10 @@ static int sr_probe(struct device *dev) return 0; +fail_minor: + spin_lock(&sr_index_lock); + clear_bit(minor, sr_index_bits); + spin_unlock(&sr_index_lock); fail_put: put_disk(disk); mutex_destroy(&cd->lock); -- cgit v1.2.3 From 4919b33b63c8b69d8dcf2b867431d0e3b6dc6d28 Mon Sep 17 00:00:00 2001 From: Tyrel Datwyler Date: Wed, 3 Jun 2020 15:36:32 -0500 Subject: scsi: ibmvscsi: Don't send host info in adapter info MAD after LPM The adapter info MAD is used to send the client info and receive the host info as a response. A persistent buffer is used and as such the client info is overwritten after the response. During the course of a normal adapter reset the client info is refreshed in the buffer in preparation for sending the adapter info MAD. However, in the special case of LPM where we reenable the CRQ instead of a full CRQ teardown and reset we fail to refresh the client info in the adapter info buffer. As a result, after Live Partition Migration (LPM) we erroneously report the host's info as our own. [mkp: typos] Link: https://lore.kernel.org/r/20200603203632.18426-1-tyreld@linux.ibm.com Signed-off-by: Tyrel Datwyler Signed-off-by: Martin K. Petersen --- drivers/scsi/ibmvscsi/ibmvscsi.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/scsi') diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c index be173135e05e..392e7681d866 100644 --- a/drivers/scsi/ibmvscsi/ibmvscsi.c +++ b/drivers/scsi/ibmvscsi/ibmvscsi.c @@ -415,6 +415,8 @@ static int ibmvscsi_reenable_crq_queue(struct crq_queue *queue, int rc = 0; struct vio_dev *vdev = to_vio_dev(hostdata->dev); + set_adapter_info(hostdata); + /* Re-enable the CRQ */ do { if (rc) -- cgit v1.2.3 From 89dd9ce784fb64e732676b7958a0278750304567 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 5 Jun 2020 14:02:58 +0300 Subject: scsi: cxlflash: Remove an unnecessary NULL check The "cmd" pointer was already dereferenced a couple lines earlier so this NULL check is too late. Fortunately, the pointer can never be NULL and the check can be removed. Link: https://lore.kernel.org/r/20200605110258.GD978434@mwanda Signed-off-by: Dan Carpenter Signed-off-by: Martin K. Petersen --- drivers/scsi/cxlflash/main.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/cxlflash/main.c b/drivers/scsi/cxlflash/main.c index fcc5aa9f6014..94250ebe9e80 100644 --- a/drivers/scsi/cxlflash/main.c +++ b/drivers/scsi/cxlflash/main.c @@ -47,9 +47,6 @@ static void process_cmd_err(struct afu_cmd *cmd, struct scsi_cmnd *scp) struct sisl_ioasa *ioasa; u32 resid; - if (unlikely(!cmd)) - return; - ioasa = &(cmd->sa); if (ioasa->rc.flags & SISL_RC_FLAGS_UNDERRUN) { -- cgit v1.2.3 From f47c24033a1ac3a08e745f50a28c3dd2c5cceda2 Mon Sep 17 00:00:00 2001 From: Denis Efremov Date: Fri, 5 Jun 2020 10:59:34 +0300 Subject: scsi: storvsc: Remove memset before memory freeing in storvsc_suspend() Remove memset with 0 for stor_device->stor_chns in storvsc_suspend() before the call to kfree() as the memory contains no sensitive information. Link: https://lore.kernel.org/r/20200605075934.8403-1-efremov@linux.com Fixes: 56fb10585934 ("scsi: storvsc: Add the support of hibernation") Suggested-by: Dexuan Cui Reviewed-by: Dexuan Cui Signed-off-by: Denis Efremov Signed-off-by: Martin K. Petersen --- drivers/scsi/storvsc_drv.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index fb41636519ee..59bf028ad682 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -1955,9 +1955,6 @@ static int storvsc_suspend(struct hv_device *hv_dev) vmbus_close(hv_dev->channel); - memset(stor_device->stor_chns, 0, - num_possible_cpus() * sizeof(void *)); - kfree(stor_device->stor_chns); stor_device->stor_chns = NULL; -- cgit v1.2.3 From 42c76c9848e13dbe0538d7ae0147a269dfa859cb Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Sat, 30 May 2020 10:16:22 +0200 Subject: scsi: acornscsi: Fix an error handling path in acornscsi_probe() 'ret' is known to be 0 at this point. Explicitly return -ENOMEM if one of the 'ecardm_iomap()' calls fail. Link: https://lore.kernel.org/r/20200530081622.577888-1-christophe.jaillet@wanadoo.fr Fixes: e95a1b656a98 ("[ARM] rpc: acornscsi: update to new style ecard driver") Signed-off-by: Christophe JAILLET Signed-off-by: Martin K. Petersen --- drivers/scsi/arm/acornscsi.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/arm/acornscsi.c b/drivers/scsi/arm/acornscsi.c index ddb52e7ba622..9a912fd0f70b 100644 --- a/drivers/scsi/arm/acornscsi.c +++ b/drivers/scsi/arm/acornscsi.c @@ -2911,8 +2911,10 @@ static int acornscsi_probe(struct expansion_card *ec, const struct ecard_id *id) ashost->base = ecardm_iomap(ec, ECARD_RES_MEMC, 0, 0); ashost->fast = ecardm_iomap(ec, ECARD_RES_IOCFAST, 0, 0); - if (!ashost->base || !ashost->fast) + if (!ashost->base || !ashost->fast) { + ret = -ENOMEM; goto out_put; + } host->irq = ec->irq; ashost->host = host; -- cgit v1.2.3