From bdb2b8cab4392ce41ddfbd6773a3da3334daf836 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Tue, 24 Jun 2008 14:03:14 -0400 Subject: [PATCH 1/5] [SCSI] erase invalid data returned by device This patch (as1108) fixes a problem that can occur with certain USB mass-storage devices: They return invalid data together with a residue indicating that the data should be ignored. Rather than leave the invalid data in a transfer buffer, where it can get misinterpreted, the patch clears the invalid portion of the buffer. This solves a problem (wrong write-protect setting detected) reported by Maciej Rutecki and Peter Teoh. Signed-off-by: Alan Stern Tested-by: Peter Teoh Signed-off-by: James Bottomley --- drivers/scsi/scsi_lib.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index a82d2fe80fb5..cbf55d59a54c 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -207,6 +207,15 @@ int scsi_execute(struct scsi_device *sdev, const unsigned char *cmd, */ blk_execute_rq(req->q, NULL, req, 1); + /* + * Some devices (USB mass-storage in particular) may transfer + * garbage data together with a residue indicating that the data + * is invalid. Prevent the garbage from being misinterpreted + * and prevent security leaks by zeroing out the excess data. + */ + if (unlikely(req->data_len > 0 && req->data_len <= bufflen)) + memset(buffer + (bufflen - req->data_len), 0, req->data_len); + ret = req->errors; out: blk_put_request(req); From 081a5bcb39b455405d58f79bb3c9398a9d4477ed Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Mon, 7 Jul 2008 11:24:06 -0500 Subject: [PATCH 2/5] [SCSI] mptspi: fix oops in mptspi_dv_renegotiate_work() The problem here is that if the ioc faults too early in the bring up sequence (as it usually does for an irq routing problem), ioc_reset gets called before the scsi host is even allocated. This causes an oops when it later schedules a renegotiation. Fix this by checking ioc->sh before trying to renegotiate. Cc: "Moore, Eric" Cc: Stable Tree Signed-off-by: James Bottomley --- drivers/message/fusion/mptspi.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/message/fusion/mptspi.c b/drivers/message/fusion/mptspi.c index 25bcfcf36f2e..1effca4e40e1 100644 --- a/drivers/message/fusion/mptspi.c +++ b/drivers/message/fusion/mptspi.c @@ -1266,13 +1266,18 @@ mptspi_dv_renegotiate(struct _MPT_SCSI_HOST *hd) static int mptspi_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) { - struct _MPT_SCSI_HOST *hd = shost_priv(ioc->sh); int rc; rc = mptscsih_ioc_reset(ioc, reset_phase); - if (reset_phase == MPT_IOC_POST_RESET) + /* only try to do a renegotiation if we're properly set up + * if we get an ioc fault on bringup, ioc->sh will be NULL */ + if (reset_phase == MPT_IOC_POST_RESET && + ioc->sh) { + struct _MPT_SCSI_HOST *hd = shost_priv(ioc->sh); + mptspi_dv_renegotiate(hd); + } return rc; } From 0ce3a7e5bd305e96c924fab1e3126480c665f017 Mon Sep 17 00:00:00 2001 From: Brian King Date: Fri, 11 Jul 2008 13:37:50 -0500 Subject: [PATCH 3/5] [SCSI] ipr: Fix HDIO_GET_IDENTITY oops for SATA devices Currently, ipr does not support HDIO_GET_IDENTITY to SATA devices. An oops occurs if userspace attempts to send the command. Since hald issues the command, ensure we fail the ioctl in ipr. This is a temporary solution to the oops. Once the ipr libata EH conversion is upstream, ipr will fully support HDIO_GET_IDENTITY. Tested-by: Milton Miller Signed-off-by: Brian King Signed-off-by: James Bottomley --- drivers/scsi/ipr.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index 999e91ea7451..e7a3a6554425 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c @@ -71,6 +71,7 @@ #include #include #include +#include #include #include #include @@ -4913,8 +4914,11 @@ static int ipr_ioctl(struct scsi_device *sdev, int cmd, void __user *arg) struct ipr_resource_entry *res; res = (struct ipr_resource_entry *)sdev->hostdata; - if (res && ipr_is_gata(res)) + if (res && ipr_is_gata(res)) { + if (cmd == HDIO_GET_IDENTITY) + return -ENOTTY; return ata_scsi_ioctl(sdev, cmd, arg); + } return -EINVAL; } From 27898988174bb211fd962ea73b9c6dc09f888705 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Thu, 10 Jul 2008 22:10:55 -0500 Subject: [PATCH 4/5] [SCSI] fusion: default MSI to disabled for SPI and FC controllers There's a fault on the FC controllers that makes them not respond correctly to MSI. The SPI controllers are fine, but are likely to be onboard on older motherboards which don't handle MSI correctly, so default both these cases to disabled. Enable by setting the module parameter mpt_msi_enable=1. For the SAS case, enable MSI by default, but it can be disabled by setting the module parameter mpt_msi_enable=0. Cc: "Prakash, Sathya" Signed-off-by: James Bottomley --- drivers/message/fusion/mptbase.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c index db3c892f87fb..d40d6d15ae20 100644 --- a/drivers/message/fusion/mptbase.c +++ b/drivers/message/fusion/mptbase.c @@ -1686,9 +1686,14 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id) ioc->bus_type = SAS; } - if (ioc->bus_type == SAS && mpt_msi_enable == -1) - ioc->msi_enable = 1; - else + if (mpt_msi_enable == -1) { + /* Enable on SAS, disable on FC and SPI */ + if (ioc->bus_type == SAS) + ioc->msi_enable = 1; + else + ioc->msi_enable = 0; + } else + /* follow flag: 0 - disable; 1 - enable */ ioc->msi_enable = mpt_msi_enable; if (ioc->errata_flag_1064) From 8df5fc042c8e7c08dc438c8198b62407ee1e91a0 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Mon, 7 Jul 2008 15:50:01 -0500 Subject: [PATCH 5/5] [SCSI] bsg: fix oops on remove If you do a modremove of any sas driver, you run into an oops on shutdown when the host is removed (coming from the host bsg device). The root cause seems to be that there's a use after free of the bsg_class_device: In bsg_kref_release_function, this is used (to do a put_device(bcg->parent) after bcg->release has been called. In sas (and possibly many other things) bcd->release frees the queue which contains the bsg_class_device, so we get a put_device on unreferenced memory. Fix this by taking a copy of the pointer to the parent before releasing bsg. Acked-by: FUJITA Tomonori Signed-off-by: James Bottomley --- block/bsg.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/block/bsg.c b/block/bsg.c index f0b7cd343216..54d617f7df3e 100644 --- a/block/bsg.c +++ b/block/bsg.c @@ -709,11 +709,12 @@ static void bsg_kref_release_function(struct kref *kref) { struct bsg_class_device *bcd = container_of(kref, struct bsg_class_device, ref); + struct device *parent = bcd->parent; if (bcd->release) bcd->release(bcd->parent); - put_device(bcd->parent); + put_device(parent); } static int bsg_put_device(struct bsg_device *bd)