scsi: mpi3mr: Add support for DSN secure firmware check
authorKashyap Desai <kashyap.desai@broadcom.com>
Thu, 20 May 2021 15:25:43 +0000 (20:55 +0530)
committerMartin K. Petersen <martin.petersen@oracle.com>
Wed, 2 Jun 2021 04:56:17 +0000 (00:56 -0400)
Read PCI_EXT_CAP_ID_DSN to query security status.

The driver will throw a warning message when a non-secure type controller
is detected. The purpose of this interface 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.

Link: https://lore.kernel.org/r/20210520152545.2710479-23-kashyap.desai@broadcom.com
Cc: sathya.prakash@broadcom.com
Reviewed-by: Hannes Reinecke <hare@suse.de>
Reviewed-by: Tomas Henzl <thenzl@redhat.com>
Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com>
Signed-off-by: Kashyap Desai <kashyap.desai@broadcom.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/scsi/mpi3mr/mpi3mr.h
drivers/scsi/mpi3mr/mpi3mr_os.c

index 372ce0e6d3e4f2616816a70477606b8c49f8fed6..e7505b468a37608af79322f9be6874c44b55379b 100644 (file)
@@ -154,6 +154,15 @@ extern struct list_head mrioc_list;
 #define MPI3MR_IRQ_POLL_SLEEP                  2
 #define MPI3MR_IRQ_POLL_TRIGGER_IOCOUNT                8
 
+/* Definitions for the controller security status*/
+#define MPI3MR_CTLR_SECURITY_STATUS_MASK       0x0C
+#define MPI3MR_CTLR_SECURE_DBG_STATUS_MASK     0x02
+
+#define MPI3MR_INVALID_DEVICE                  0x00
+#define MPI3MR_CONFIG_SECURE_DEVICE            0x04
+#define MPI3MR_HARD_SECURE_DEVICE              0x08
+#define MPI3MR_TAMPERED_DEVICE                 0x0C
+
 /* SGE Flag definition */
 #define MPI3MR_SGEFLAGS_SYSTEM_SIMPLE_END_OF_LIST \
        (MPI3_SGE_FLAGS_ELEMENT_TYPE_SIMPLE | MPI3_SGE_FLAGS_DLAS_SYSTEM | \
index dd71cdc5945cf571691657f8529b8345b5ac7c22..6400ca57fb1eca57a2cd86b57d26d5a55f5f0de5 100644 (file)
@@ -3188,6 +3188,75 @@ static inline void mpi3mr_init_drv_cmd(struct mpi3mr_drv_cmd *cmdptr,
        cmdptr->host_tag = host_tag;
 }
 
+/**
+ * osintfc_mrioc_security_status -Check controller secure status
+ * @pdev: PCI device instance
+ *
+ * Read the Device Serial Number capability from PCI config
+ * space and decide whether the controller is secure or not.
+ *
+ * Return: 0 on success, non-zero on failure.
+ */
+static int
+osintfc_mrioc_security_status(struct pci_dev *pdev)
+{
+       u32 cap_data;
+       int base;
+       u32 ctlr_status;
+       u32 debug_status;
+       int retval = 0;
+
+       base = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_DSN);
+       if (!base) {
+               dev_err(&pdev->dev,
+                   "%s: PCI_EXT_CAP_ID_DSN is not supported\n", __func__);
+               return -1;
+       }
+
+       pci_read_config_dword(pdev, base + 4, &cap_data);
+
+       debug_status = cap_data & MPI3MR_CTLR_SECURE_DBG_STATUS_MASK;
+       ctlr_status = cap_data & MPI3MR_CTLR_SECURITY_STATUS_MASK;
+
+       switch (ctlr_status) {
+       case MPI3MR_INVALID_DEVICE:
+               dev_err(&pdev->dev,
+                   "%s: Non secure ctlr (Invalid) is detected: DID: 0x%x: SVID: 0x%x: SDID: 0x%x\n",
+                   __func__, pdev->device, pdev->subsystem_vendor,
+                   pdev->subsystem_device);
+               retval = -1;
+               break;
+       case MPI3MR_CONFIG_SECURE_DEVICE:
+               if (!debug_status)
+                       dev_info(&pdev->dev,
+                           "%s: Config secure ctlr is detected\n",
+                           __func__);
+               break;
+       case MPI3MR_HARD_SECURE_DEVICE:
+               break;
+       case MPI3MR_TAMPERED_DEVICE:
+               dev_err(&pdev->dev,
+                   "%s: Non secure ctlr (Tampered) is detected: DID: 0x%x: SVID: 0x%x: SDID: 0x%x\n",
+                   __func__, pdev->device, pdev->subsystem_vendor,
+                   pdev->subsystem_device);
+               retval = -1;
+               break;
+       default:
+               retval = -1;
+                       break;
+       }
+
+       if (!retval && debug_status) {
+               dev_err(&pdev->dev,
+                   "%s: Non secure ctlr (Secure Dbg) is detected: DID: 0x%x: SVID: 0x%x: SDID: 0x%x\n",
+                   __func__, pdev->device, pdev->subsystem_vendor,
+                   pdev->subsystem_device);
+               retval = -1;
+       }
+
+       return retval;
+}
+
 /**
  * mpi3mr_probe - PCI probe callback
  * @pdev: PCI device instance
@@ -3210,6 +3279,11 @@ mpi3mr_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        struct Scsi_Host *shost = NULL;
        int retval = 0, i;
 
+       if (osintfc_mrioc_security_status(pdev)) {
+               warn_non_secure_ctlr = 1;
+               return 1; /* For Invalid and Tampered device */
+       }
+
        shost = scsi_host_alloc(&mpi3mr_driver_template,
            sizeof(struct mpi3mr_ioc));
        if (!shost) {
@@ -3326,6 +3400,9 @@ static void mpi3mr_remove(struct pci_dev *pdev)
        unsigned long flags;
        struct mpi3mr_tgt_dev *tgtdev, *tgtdev_next;
 
+       if (!shost)
+               return;
+
        mrioc = shost_priv(shost);
        while (mrioc->reset_in_progress || mrioc->is_driver_loading)
                ssleep(1);
@@ -3444,6 +3521,9 @@ static int mpi3mr_resume(struct pci_dev *pdev)
        pci_power_t device_state = pdev->current_state;
        int r;
 
+       if (!shost)
+               return 0;
+
        mrioc = shost_priv(shost);
 
        ioc_info(mrioc, "pdev=0x%p, slot=%s, previous operating state [D%d]\n",