Skip to content

Commit 5f096b1

Browse files
committed
vfio: Whitelist PCI bridges
When determining whether a group is viable, we already allow devices bound to pcieport. Generalize this to include any PCI bridge device. Signed-off-by: Alex Williamson <[email protected]>
1 parent 32b8819 commit 5f096b1

File tree

1 file changed

+25
-6
lines changed

1 file changed

+25
-6
lines changed

drivers/vfio/vfio.c

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include <linux/miscdevice.h>
2626
#include <linux/module.h>
2727
#include <linux/mutex.h>
28+
#include <linux/pci.h>
2829
#include <linux/rwsem.h>
2930
#include <linux/sched.h>
3031
#include <linux/slab.h>
@@ -438,16 +439,33 @@ static struct vfio_device *vfio_group_get_device(struct vfio_group *group,
438439
}
439440

440441
/*
441-
* Whitelist some drivers that we know are safe (no dma) or just sit on
442-
* a device. It's not always practical to leave a device within a group
443-
* driverless as it could get re-bound to something unsafe.
442+
* Some drivers, like pci-stub, are only used to prevent other drivers from
443+
* claiming a device and are therefore perfectly legitimate for a user owned
444+
* group. The pci-stub driver has no dependencies on DMA or the IOVA mapping
445+
* of the device, but it does prevent the user from having direct access to
446+
* the device, which is useful in some circumstances.
447+
*
448+
* We also assume that we can include PCI interconnect devices, ie. bridges.
449+
* IOMMU grouping on PCI necessitates that if we lack isolation on a bridge
450+
* then all of the downstream devices will be part of the same IOMMU group as
451+
* the bridge. Thus, if placing the bridge into the user owned IOVA space
452+
* breaks anything, it only does so for user owned devices downstream. Note
453+
* that error notification via MSI can be affected for platforms that handle
454+
* MSI within the same IOVA space as DMA.
444455
*/
445-
static const char * const vfio_driver_whitelist[] = { "pci-stub", "pcieport" };
456+
static const char * const vfio_driver_whitelist[] = { "pci-stub" };
446457

447-
static bool vfio_whitelisted_driver(struct device_driver *drv)
458+
static bool vfio_dev_whitelisted(struct device *dev, struct device_driver *drv)
448459
{
449460
int i;
450461

462+
if (dev_is_pci(dev)) {
463+
struct pci_dev *pdev = to_pci_dev(dev);
464+
465+
if (pdev->hdr_type != PCI_HEADER_TYPE_NORMAL)
466+
return true;
467+
}
468+
451469
for (i = 0; i < ARRAY_SIZE(vfio_driver_whitelist); i++) {
452470
if (!strcmp(drv->name, vfio_driver_whitelist[i]))
453471
return true;
@@ -462,6 +480,7 @@ static bool vfio_whitelisted_driver(struct device_driver *drv)
462480
* - driver-less
463481
* - bound to a vfio driver
464482
* - bound to a whitelisted driver
483+
* - a PCI interconnect device
465484
*
466485
* We use two methods to determine whether a device is bound to a vfio
467486
* driver. The first is to test whether the device exists in the vfio
@@ -486,7 +505,7 @@ static int vfio_dev_viable(struct device *dev, void *data)
486505
}
487506
mutex_unlock(&group->unbound_lock);
488507

489-
if (!ret || !drv || vfio_whitelisted_driver(drv))
508+
if (!ret || !drv || vfio_dev_whitelisted(dev, drv))
490509
return 0;
491510

492511
device = vfio_group_get_device(group, dev);

0 commit comments

Comments
 (0)