On Wed, 13 Feb 2019 11:28:21 -0500 Konrad Rzeszutek Wilk <konrad.wilk@xxxxxxxxxx> wrote: > On Wed, Feb 13, 2019 at 11:14:06AM +0100, Eric Auger wrote: > > pci_map_rom/pci_get_rom_size() performs memory access in the ROM. > > In case the Memory Space accesses were disabled, readw() is likely to > > crash the host with a synchronous external abort (aarch64). > > Ouch. Is there an CVE for this? > > Also I think this can cause x86 machines to blow up. > > See https://xenbits.xen.org/xsa/advisory-120.html The far more common response to a target abort on x86 is simply a -1 return. Device assignment quickly becomes unfeasible in the general case, as outlined in the above link by restricting only to SR-IOV VFs, if we try to claim there is no possible way that the device cannot trigger a fatal error on the host. Systems implementing APEI pretty much guarantee that by escalating device specific faults to fatal errors and removing the host OS from the error handling path. Some platforms will even trigger a fatal error for a DMA outside of the range mapped for the device by the IOMMU. We can't probe for this behavior to restrict the devices, we cannot know how DMA is programmed for every device in order to babysit it, nor can we guarantee that the PCI config space command register is the only way a device manages access to I/O resources hosted on the device. Restricting user access to the command register therefore seems like a false sense of security, potentially with behavioral issues to the user. It would be great if we always had a hook into the error handling path such that we could declare this as a user generated fault, kill the user process, and keep running, but we're limited by the error handling capabilities of the hardware and the degree to which the platform/firmware allows OS control of that error handling. Thanks, Alex > > > > In case memory accesses were disabled, re-enable them before the call > > and disable them back again just after. > > > > Signed-off-by: Eric Auger <eric.auger@xxxxxxxxxx> > > --- > > drivers/vfio/pci/vfio_pci.c | 14 ++++++++++++++ > > 1 file changed, 14 insertions(+) > > > > diff --git a/drivers/vfio/pci/vfio_pci.c b/drivers/vfio/pci/vfio_pci.c > > index ff60bd1ea587..96b8bbd909d7 100644 > > --- a/drivers/vfio/pci/vfio_pci.c > > +++ b/drivers/vfio/pci/vfio_pci.c > > @@ -706,8 +706,10 @@ static long vfio_pci_ioctl(void *device_data, > > break; > > case VFIO_PCI_ROM_REGION_INDEX: > > { > > + bool mem_access_disabled; > > void __iomem *io; > > size_t size; > > + u16 cmd; > > > > info.offset = VFIO_PCI_INDEX_TO_OFFSET(info.index); > > info.flags = 0; > > @@ -723,6 +725,13 @@ static long vfio_pci_ioctl(void *device_data, > > break; > > } > > > > + pci_read_config_word(pdev, PCI_COMMAND, &cmd); > > + mem_access_disabled = !(cmd & PCI_COMMAND_MEMORY); > > + if (mem_access_disabled) { > > + cmd |= PCI_COMMAND_MEMORY; > > + pci_write_config_word(pdev, PCI_COMMAND, cmd); > > + } > > + > > /* Is it really there? */ > > io = pci_map_rom(pdev, &size); > > if (!io || !size) { > > @@ -731,6 +740,11 @@ static long vfio_pci_ioctl(void *device_data, > > } > > pci_unmap_rom(pdev, io); > > > > + if (mem_access_disabled) { > > + cmd &= ~PCI_COMMAND_MEMORY; > > + pci_write_config_word(pdev, PCI_COMMAND, cmd); > > + } > > + > > info.flags = VFIO_REGION_INFO_FLAG_READ; > > break; > > } > > -- > > 2.20.1 > >