diff options
author | Alex Williamson <alex.williamson@redhat.com> | 2015-10-27 16:53:04 -0400 |
---|---|---|
committer | Alex Williamson <alex.williamson@redhat.com> | 2015-10-27 16:53:04 -0400 |
commit | 5f096b14d421ba23249b752e41989ecfaa6ae226 (patch) | |
tree | 6fdfa589dc0888699202d9545779b52fab71a976 /drivers/vfio | |
parent | 32b88194f71d6ae7768a29f87fbba454728273ee (diff) |
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 <alex.williamson@redhat.com>
Diffstat (limited to 'drivers/vfio')
-rw-r--r-- | drivers/vfio/vfio.c | 31 |
1 files changed, 25 insertions, 6 deletions
diff --git a/drivers/vfio/vfio.c b/drivers/vfio/vfio.c index 563c510f285c..1c0f98c2f634 100644 --- a/drivers/vfio/vfio.c +++ b/drivers/vfio/vfio.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/miscdevice.h> | 25 | #include <linux/miscdevice.h> |
26 | #include <linux/module.h> | 26 | #include <linux/module.h> |
27 | #include <linux/mutex.h> | 27 | #include <linux/mutex.h> |
28 | #include <linux/pci.h> | ||
28 | #include <linux/rwsem.h> | 29 | #include <linux/rwsem.h> |
29 | #include <linux/sched.h> | 30 | #include <linux/sched.h> |
30 | #include <linux/slab.h> | 31 | #include <linux/slab.h> |
@@ -438,16 +439,33 @@ static struct vfio_device *vfio_group_get_device(struct vfio_group *group, | |||
438 | } | 439 | } |
439 | 440 | ||
440 | /* | 441 | /* |
441 | * Whitelist some drivers that we know are safe (no dma) or just sit on | 442 | * Some drivers, like pci-stub, are only used to prevent other drivers from |
442 | * a device. It's not always practical to leave a device within a group | 443 | * claiming a device and are therefore perfectly legitimate for a user owned |
443 | * driverless as it could get re-bound to something unsafe. | 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. | ||
444 | */ | 455 | */ |
445 | static const char * const vfio_driver_whitelist[] = { "pci-stub", "pcieport" }; | 456 | static const char * const vfio_driver_whitelist[] = { "pci-stub" }; |
446 | 457 | ||
447 | static bool vfio_whitelisted_driver(struct device_driver *drv) | 458 | static bool vfio_dev_whitelisted(struct device *dev, struct device_driver *drv) |
448 | { | 459 | { |
449 | int i; | 460 | int i; |
450 | 461 | ||
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 | |||
451 | for (i = 0; i < ARRAY_SIZE(vfio_driver_whitelist); i++) { | 469 | for (i = 0; i < ARRAY_SIZE(vfio_driver_whitelist); i++) { |
452 | if (!strcmp(drv->name, vfio_driver_whitelist[i])) | 470 | if (!strcmp(drv->name, vfio_driver_whitelist[i])) |
453 | return true; | 471 | return true; |
@@ -462,6 +480,7 @@ static bool vfio_whitelisted_driver(struct device_driver *drv) | |||
462 | * - driver-less | 480 | * - driver-less |
463 | * - bound to a vfio driver | 481 | * - bound to a vfio driver |
464 | * - bound to a whitelisted driver | 482 | * - bound to a whitelisted driver |
483 | * - a PCI interconnect device | ||
465 | * | 484 | * |
466 | * We use two methods to determine whether a device is bound to a vfio | 485 | * We use two methods to determine whether a device is bound to a vfio |
467 | * driver. The first is to test whether the device exists in the vfio | 486 | * 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) | |||
486 | } | 505 | } |
487 | mutex_unlock(&group->unbound_lock); | 506 | mutex_unlock(&group->unbound_lock); |
488 | 507 | ||
489 | if (!ret || !drv || vfio_whitelisted_driver(drv)) | 508 | if (!ret || !drv || vfio_dev_whitelisted(dev, drv)) |
490 | return 0; | 509 | return 0; |
491 | 510 | ||
492 | device = vfio_group_get_device(group, dev); | 511 | device = vfio_group_get_device(group, dev); |