|
|
From a8fa1817bd98ccc79eefa6b2e779afb3be6b2e56 Mon Sep 17 00:00:00 2001
|
|
|
From: Tomas Henzl <thenzl@redhat.com>
|
|
|
Date: Fri, 9 Oct 2020 14:06:34 -0400
|
|
|
Subject: [PATCH 16/33] [scsi] scsi: mpt3sas: Detect tampered Aero and Sea
|
|
|
adapters
|
|
|
|
|
|
Message-id: <20201009140636.7976-17-thenzl@redhat.com>
|
|
|
Patchwork-id: 330371
|
|
|
Patchwork-instance: patchwork
|
|
|
O-Subject: [RHEL8.4 e-stor PATCH 16/18] scsi: mpt3sas: Detect tampered Aero and Sea adapters
|
|
|
Bugzilla: 1851440
|
|
|
RH-Acked-by: Ewan Milne <emilne@redhat.com>
|
|
|
RH-Acked-by: Jarod Wilson <jarod@redhat.com>
|
|
|
RH-Acked-by: Maurizio Lombardi <mlombard@redhat.com>
|
|
|
RH-Acked-by: Tony Camuso <tcamuso@redhat.com>
|
|
|
|
|
|
The driver will throw an error message when a tampered type controller
|
|
|
is detected. The intent is to avoid interacting with any firmware
|
|
|
which is not secured/signed by Broadcom. Any tampering on firmware
|
|
|
component will be detected by hardware and it will be communicated to
|
|
|
the driver to avoid any further interaction with that component.
|
|
|
|
|
|
[mkp: switched back to dev_err]
|
|
|
|
|
|
Link: https://lore.kernel.org/r/20200814130426.2741171-1-sreekanth.reddy@broadcom.com
|
|
|
Signed-off-by: Sreekanth Reddy <sreekanth.reddy@broadcom.com>
|
|
|
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
|
|
|
(cherry picked from commit f38c43a0e9007e1f21a47a199643a16666902928)
|
|
|
Signed-off-by: Tomas Henzl <thenzl@redhat.com>
|
|
|
Signed-off-by: Jan Stancek <jstancek@redhat.com>
|
|
|
---
|
|
|
drivers/scsi/mpt3sas/mpt3sas_scsih.c | 121 ++++++++++++++++++++++++++++++-----
|
|
|
1 file changed, 105 insertions(+), 16 deletions(-)
|
|
|
|
|
|
diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
|
|
|
index 8e9edfd8239c..8c14908e39ca 100644
|
|
|
--- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c
|
|
|
+++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
|
|
|
@@ -10092,6 +10092,34 @@ _scsih_ir_shutdown(struct MPT3SAS_ADAPTER *ioc)
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
+ * _scsih_get_shost_and_ioc - get shost and ioc
|
|
|
+ * and verify whether they are NULL or not
|
|
|
+ * @pdev: PCI device struct
|
|
|
+ * @shost: address of scsi host pointer
|
|
|
+ * @ioc: address of HBA adapter pointer
|
|
|
+ *
|
|
|
+ * Return zero if *shost and *ioc are not NULL otherwise return error number.
|
|
|
+ */
|
|
|
+static int
|
|
|
+_scsih_get_shost_and_ioc(struct pci_dev *pdev,
|
|
|
+ struct Scsi_Host **shost, struct MPT3SAS_ADAPTER **ioc)
|
|
|
+{
|
|
|
+ *shost = pci_get_drvdata(pdev);
|
|
|
+ if (*shost == NULL) {
|
|
|
+ dev_err(&pdev->dev, "pdev's driver data is null\n");
|
|
|
+ return -ENXIO;
|
|
|
+ }
|
|
|
+
|
|
|
+ *ioc = shost_priv(*shost);
|
|
|
+ if (*ioc == NULL) {
|
|
|
+ dev_err(&pdev->dev, "shost's private data is null\n");
|
|
|
+ return -ENXIO;
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
* scsih_remove - detach and remove add host
|
|
|
* @pdev: PCI device struct
|
|
|
*
|
|
|
@@ -10099,8 +10127,8 @@ _scsih_ir_shutdown(struct MPT3SAS_ADAPTER *ioc)
|
|
|
*/
|
|
|
static void scsih_remove(struct pci_dev *pdev)
|
|
|
{
|
|
|
- struct Scsi_Host *shost = pci_get_drvdata(pdev);
|
|
|
- struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
|
|
|
+ struct Scsi_Host *shost;
|
|
|
+ struct MPT3SAS_ADAPTER *ioc;
|
|
|
struct _sas_port *mpt3sas_port, *next_port;
|
|
|
struct _raid_device *raid_device, *next;
|
|
|
struct MPT3SAS_TARGET *sas_target_priv_data;
|
|
|
@@ -10109,6 +10137,9 @@ static void scsih_remove(struct pci_dev *pdev)
|
|
|
unsigned long flags;
|
|
|
Mpi2ConfigReply_t mpi_reply;
|
|
|
|
|
|
+ if (_scsih_get_shost_and_ioc(pdev, &shost, &ioc))
|
|
|
+ return;
|
|
|
+
|
|
|
ioc->remove_host = 1;
|
|
|
|
|
|
if (!pci_device_is_present(pdev))
|
|
|
@@ -10188,12 +10219,15 @@ static void scsih_remove(struct pci_dev *pdev)
|
|
|
static void
|
|
|
scsih_shutdown(struct pci_dev *pdev)
|
|
|
{
|
|
|
- struct Scsi_Host *shost = pci_get_drvdata(pdev);
|
|
|
- struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
|
|
|
+ struct Scsi_Host *shost;
|
|
|
+ struct MPT3SAS_ADAPTER *ioc;
|
|
|
struct workqueue_struct *wq;
|
|
|
unsigned long flags;
|
|
|
Mpi2ConfigReply_t mpi_reply;
|
|
|
|
|
|
+ if (_scsih_get_shost_and_ioc(pdev, &shost, &ioc))
|
|
|
+ return;
|
|
|
+
|
|
|
ioc->remove_host = 1;
|
|
|
|
|
|
if (!pci_device_is_present(pdev))
|
|
|
@@ -10764,6 +10798,10 @@ _scsih_determine_hba_mpi_version(struct pci_dev *pdev)
|
|
|
case MPI26_MFGPAGE_DEVID_HARD_SEC_3916:
|
|
|
case MPI26_MFGPAGE_DEVID_CFG_SEC_3816:
|
|
|
case MPI26_MFGPAGE_DEVID_HARD_SEC_3816:
|
|
|
+ case MPI26_MFGPAGE_DEVID_INVALID0_3916:
|
|
|
+ case MPI26_MFGPAGE_DEVID_INVALID1_3916:
|
|
|
+ case MPI26_MFGPAGE_DEVID_INVALID0_3816:
|
|
|
+ case MPI26_MFGPAGE_DEVID_INVALID1_3816:
|
|
|
return MPI26_VERSION;
|
|
|
}
|
|
|
return 0;
|
|
|
@@ -10853,6 +10891,20 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
|
|
case MPI26_ATLAS_PCIe_SWITCH_DEVID:
|
|
|
ioc->is_gen35_ioc = 1;
|
|
|
break;
|
|
|
+ case MPI26_MFGPAGE_DEVID_INVALID0_3816:
|
|
|
+ case MPI26_MFGPAGE_DEVID_INVALID0_3916:
|
|
|
+ dev_err(&pdev->dev,
|
|
|
+ "HBA with DeviceId 0x%04x, sub VendorId 0x%04x, sub DeviceId 0x%04x is Invalid",
|
|
|
+ pdev->device, pdev->subsystem_vendor,
|
|
|
+ pdev->subsystem_device);
|
|
|
+ return 1;
|
|
|
+ case MPI26_MFGPAGE_DEVID_INVALID1_3816:
|
|
|
+ case MPI26_MFGPAGE_DEVID_INVALID1_3916:
|
|
|
+ dev_err(&pdev->dev,
|
|
|
+ "HBA with DeviceId 0x%04x, sub VendorId 0x%04x, sub DeviceId 0x%04x is Tampered",
|
|
|
+ pdev->device, pdev->subsystem_vendor,
|
|
|
+ pdev->subsystem_device);
|
|
|
+ return 1;
|
|
|
case MPI26_MFGPAGE_DEVID_CFG_SEC_3816:
|
|
|
case MPI26_MFGPAGE_DEVID_CFG_SEC_3916:
|
|
|
dev_info(&pdev->dev,
|
|
|
@@ -11044,9 +11096,14 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
|
|
static int
|
|
|
scsih_suspend(struct pci_dev *pdev, pm_message_t state)
|
|
|
{
|
|
|
- struct Scsi_Host *shost = pci_get_drvdata(pdev);
|
|
|
- struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
|
|
|
+ struct Scsi_Host *shost;
|
|
|
+ struct MPT3SAS_ADAPTER *ioc;
|
|
|
pci_power_t device_state;
|
|
|
+ int rc;
|
|
|
+
|
|
|
+ rc = _scsih_get_shost_and_ioc(pdev, &shost, &ioc);
|
|
|
+ if (rc)
|
|
|
+ return rc;
|
|
|
|
|
|
mpt3sas_base_stop_watchdog(ioc);
|
|
|
flush_scheduled_work();
|
|
|
@@ -11071,11 +11128,15 @@ scsih_suspend(struct pci_dev *pdev, pm_message_t state)
|
|
|
static int
|
|
|
scsih_resume(struct pci_dev *pdev)
|
|
|
{
|
|
|
- struct Scsi_Host *shost = pci_get_drvdata(pdev);
|
|
|
- struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
|
|
|
+ struct Scsi_Host *shost;
|
|
|
+ struct MPT3SAS_ADAPTER *ioc;
|
|
|
pci_power_t device_state = pdev->current_state;
|
|
|
int r;
|
|
|
|
|
|
+ r = _scsih_get_shost_and_ioc(pdev, &shost, &ioc);
|
|
|
+ if (r)
|
|
|
+ return r;
|
|
|
+
|
|
|
ioc_info(ioc, "pdev=0x%p, slot=%s, previous operating state [D%d]\n",
|
|
|
pdev, pci_name(pdev), device_state);
|
|
|
|
|
|
@@ -11106,8 +11167,11 @@ scsih_resume(struct pci_dev *pdev)
|
|
|
static pci_ers_result_t
|
|
|
scsih_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state)
|
|
|
{
|
|
|
- struct Scsi_Host *shost = pci_get_drvdata(pdev);
|
|
|
- struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
|
|
|
+ struct Scsi_Host *shost;
|
|
|
+ struct MPT3SAS_ADAPTER *ioc;
|
|
|
+
|
|
|
+ if (_scsih_get_shost_and_ioc(pdev, &shost, &ioc))
|
|
|
+ return PCI_ERS_RESULT_DISCONNECT;
|
|
|
|
|
|
ioc_info(ioc, "PCI error: detected callback, state(%d)!!\n", state);
|
|
|
|
|
|
@@ -11142,10 +11206,13 @@ scsih_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state)
|
|
|
static pci_ers_result_t
|
|
|
scsih_pci_slot_reset(struct pci_dev *pdev)
|
|
|
{
|
|
|
- struct Scsi_Host *shost = pci_get_drvdata(pdev);
|
|
|
- struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
|
|
|
+ struct Scsi_Host *shost;
|
|
|
+ struct MPT3SAS_ADAPTER *ioc;
|
|
|
int rc;
|
|
|
|
|
|
+ if (_scsih_get_shost_and_ioc(pdev, &shost, &ioc))
|
|
|
+ return PCI_ERS_RESULT_DISCONNECT;
|
|
|
+
|
|
|
ioc_info(ioc, "PCI error: slot reset callback!!\n");
|
|
|
|
|
|
ioc->pci_error_recovery = 0;
|
|
|
@@ -11178,8 +11245,11 @@ scsih_pci_slot_reset(struct pci_dev *pdev)
|
|
|
static void
|
|
|
scsih_pci_resume(struct pci_dev *pdev)
|
|
|
{
|
|
|
- struct Scsi_Host *shost = pci_get_drvdata(pdev);
|
|
|
- struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
|
|
|
+ struct Scsi_Host *shost;
|
|
|
+ struct MPT3SAS_ADAPTER *ioc;
|
|
|
+
|
|
|
+ if (_scsih_get_shost_and_ioc(pdev, &shost, &ioc))
|
|
|
+ return;
|
|
|
|
|
|
ioc_info(ioc, "PCI error: resume callback!!\n");
|
|
|
|
|
|
@@ -11194,8 +11264,11 @@ scsih_pci_resume(struct pci_dev *pdev)
|
|
|
static pci_ers_result_t
|
|
|
scsih_pci_mmio_enabled(struct pci_dev *pdev)
|
|
|
{
|
|
|
- struct Scsi_Host *shost = pci_get_drvdata(pdev);
|
|
|
- struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
|
|
|
+ struct Scsi_Host *shost;
|
|
|
+ struct MPT3SAS_ADAPTER *ioc;
|
|
|
+
|
|
|
+ if (_scsih_get_shost_and_ioc(pdev, &shost, &ioc))
|
|
|
+ return PCI_ERS_RESULT_DISCONNECT;
|
|
|
|
|
|
ioc_info(ioc, "PCI error: mmio enabled callback!!\n");
|
|
|
|
|
|
@@ -11322,6 +11395,14 @@ static const struct pci_device_id mpt3sas_pci_table[] = {
|
|
|
{ MPI2_MFGPAGE_VENDORID_LSI, MPI26_MFGPAGE_DEVID_HARD_SEC_3916,
|
|
|
PCI_ANY_ID, PCI_ANY_ID },
|
|
|
|
|
|
+ /*
|
|
|
+ * Aero SI –> 0x00E0 Invalid, 0x00E3 Tampered
|
|
|
+ */
|
|
|
+ { MPI2_MFGPAGE_VENDORID_LSI, MPI26_MFGPAGE_DEVID_INVALID0_3916,
|
|
|
+ PCI_ANY_ID, PCI_ANY_ID },
|
|
|
+ { MPI2_MFGPAGE_VENDORID_LSI, MPI26_MFGPAGE_DEVID_INVALID1_3916,
|
|
|
+ PCI_ANY_ID, PCI_ANY_ID },
|
|
|
+
|
|
|
/* Atlas PCIe Switch Management Port */
|
|
|
{ MPI2_MFGPAGE_VENDORID_LSI, MPI26_ATLAS_PCIe_SWITCH_DEVID,
|
|
|
PCI_ANY_ID, PCI_ANY_ID },
|
|
|
@@ -11334,6 +11415,14 @@ static const struct pci_device_id mpt3sas_pci_table[] = {
|
|
|
{ MPI2_MFGPAGE_VENDORID_LSI, MPI26_MFGPAGE_DEVID_HARD_SEC_3816,
|
|
|
PCI_ANY_ID, PCI_ANY_ID },
|
|
|
|
|
|
+ /*
|
|
|
+ * Sea SI –> 0x00E4 Invalid, 0x00E7 Tampered
|
|
|
+ */
|
|
|
+ { MPI2_MFGPAGE_VENDORID_LSI, MPI26_MFGPAGE_DEVID_INVALID0_3816,
|
|
|
+ PCI_ANY_ID, PCI_ANY_ID },
|
|
|
+ { MPI2_MFGPAGE_VENDORID_LSI, MPI26_MFGPAGE_DEVID_INVALID1_3816,
|
|
|
+ PCI_ANY_ID, PCI_ANY_ID },
|
|
|
+
|
|
|
{0} /* Terminating entry */
|
|
|
};
|
|
|
MODULE_DEVICE_TABLE(pci, mpt3sas_pci_table);
|
|
|
--
|
|
|
2.13.6
|
|
|
|