Message ID | 20210419110156.1786882-23-kashyap.desai@broadcom.com |
---|---|
State | Superseded |
Headers | show |
Series | Introducing mpi3mr driver | expand |
> On Apr 19, 2021, at 6:01 AM, Kashyap Desai <kashyap.desai@broadcom.com> wrote: > > Read PCI_EXT_CAP_ID_DSN to know security status. > > Driver will throw an warning message when a non-secure type controller > is detected. 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. > > Signed-off-by: Kashyap Desai <kashyap.desai@broadcom.com> > Reviewed-by: Hannes Reinecke <hare@suse.de> > Reviewed-by: Tomas Henzl <thenzl@redhat.com> > > Cc: sathya.prakash@broadcom.com > --- > drivers/scsi/mpi3mr/mpi3mr.h | 9 ++++ > drivers/scsi/mpi3mr/mpi3mr_os.c | 80 +++++++++++++++++++++++++++++++++ > 2 files changed, 89 insertions(+) > > diff --git a/drivers/scsi/mpi3mr/mpi3mr.h b/drivers/scsi/mpi3mr/mpi3mr.h > index 505df0e7b852..db9cb11db3bf 100644 > --- a/drivers/scsi/mpi3mr/mpi3mr.h > +++ b/drivers/scsi/mpi3mr/mpi3mr.h > @@ -149,6 +149,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 | \ > diff --git a/drivers/scsi/mpi3mr/mpi3mr_os.c b/drivers/scsi/mpi3mr/mpi3mr_os.c > index 05473b0f3c9e..836005ce6999 100644 > --- a/drivers/scsi/mpi3mr/mpi3mr_os.c > +++ b/drivers/scsi/mpi3mr/mpi3mr_os.c > @@ -3206,6 +3206,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 > @@ -3228,6 +3297,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) { > @@ -3344,6 +3418,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); > @@ -3464,6 +3541,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", > -- > 2.18.1 > Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com> -- Himanshu Madhani Oracle Linux Engineering
diff --git a/drivers/scsi/mpi3mr/mpi3mr.h b/drivers/scsi/mpi3mr/mpi3mr.h index 505df0e7b852..db9cb11db3bf 100644 --- a/drivers/scsi/mpi3mr/mpi3mr.h +++ b/drivers/scsi/mpi3mr/mpi3mr.h @@ -149,6 +149,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 | \ diff --git a/drivers/scsi/mpi3mr/mpi3mr_os.c b/drivers/scsi/mpi3mr/mpi3mr_os.c index 05473b0f3c9e..836005ce6999 100644 --- a/drivers/scsi/mpi3mr/mpi3mr_os.c +++ b/drivers/scsi/mpi3mr/mpi3mr_os.c @@ -3206,6 +3206,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 @@ -3228,6 +3297,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) { @@ -3344,6 +3418,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); @@ -3464,6 +3541,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",