scsi: mpi3mr: Add support for DSN secure firmware check

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>
This commit is contained in:
Kashyap Desai 2021-05-20 20:55:43 +05:30 коммит произвёл Martin K. Petersen
Родитель 2f9c4d520a
Коммит 28cbe2f420
2 изменённых файлов: 89 добавлений и 0 удалений

Просмотреть файл

@ -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 | \

Просмотреть файл

@ -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",