aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Williamson <alex.williamson@redhat.com>2016-05-30 09:50:10 -0400
committerAlex Williamson <alex.williamson@redhat.com>2016-05-30 09:50:10 -0400
commit956b56a984ddf10aa69b25318dc04430101beed6 (patch)
tree5d698890a0f6ab87af4c647908395f51d30e8356
parent1a695a905c18548062509178b98bc91e67510864 (diff)
vfio/pci: Fix ordering of eventfd vs virqfd shutdown
Both the INTx and MSI/X disable paths do an eventfd_ctx_put() for the trigger eventfd before calling vfio_virqfd_disable() any potential mask and unmask eventfds. This opens a use-after-free race where an inopportune irqfd can reference the freed signalling eventfd. Reorder to avoid this possibility. Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
-rw-r--r--drivers/vfio/pci/vfio_pci_intrs.c6
1 files changed, 3 insertions, 3 deletions
diff --git a/drivers/vfio/pci/vfio_pci_intrs.c b/drivers/vfio/pci/vfio_pci_intrs.c
index e9ea3fef144a..15ecfc9c5f6c 100644
--- a/drivers/vfio/pci/vfio_pci_intrs.c
+++ b/drivers/vfio/pci/vfio_pci_intrs.c
@@ -228,9 +228,9 @@ static int vfio_intx_set_signal(struct vfio_pci_device *vdev, int fd)
228 228
229static void vfio_intx_disable(struct vfio_pci_device *vdev) 229static void vfio_intx_disable(struct vfio_pci_device *vdev)
230{ 230{
231 vfio_intx_set_signal(vdev, -1);
232 vfio_virqfd_disable(&vdev->ctx[0].unmask); 231 vfio_virqfd_disable(&vdev->ctx[0].unmask);
233 vfio_virqfd_disable(&vdev->ctx[0].mask); 232 vfio_virqfd_disable(&vdev->ctx[0].mask);
233 vfio_intx_set_signal(vdev, -1);
234 vdev->irq_type = VFIO_PCI_NUM_IRQS; 234 vdev->irq_type = VFIO_PCI_NUM_IRQS;
235 vdev->num_ctx = 0; 235 vdev->num_ctx = 0;
236 kfree(vdev->ctx); 236 kfree(vdev->ctx);
@@ -401,13 +401,13 @@ static void vfio_msi_disable(struct vfio_pci_device *vdev, bool msix)
401 struct pci_dev *pdev = vdev->pdev; 401 struct pci_dev *pdev = vdev->pdev;
402 int i; 402 int i;
403 403
404 vfio_msi_set_block(vdev, 0, vdev->num_ctx, NULL, msix);
405
406 for (i = 0; i < vdev->num_ctx; i++) { 404 for (i = 0; i < vdev->num_ctx; i++) {
407 vfio_virqfd_disable(&vdev->ctx[i].unmask); 405 vfio_virqfd_disable(&vdev->ctx[i].unmask);
408 vfio_virqfd_disable(&vdev->ctx[i].mask); 406 vfio_virqfd_disable(&vdev->ctx[i].mask);
409 } 407 }
410 408
409 vfio_msi_set_block(vdev, 0, vdev->num_ctx, NULL, msix);
410
411 if (msix) { 411 if (msix) {
412 pci_disable_msix(vdev->pdev); 412 pci_disable_msix(vdev->pdev);
413 kfree(vdev->msix); 413 kfree(vdev->msix);