Skip to content

Commit f31494b

Browse files
committed
Merge tag 'vfio-v4.8-rc2' of git://github.com/awilliam/linux-vfio
Pull VFIO fix from Alex Williamson: "Fix oops when dereferencing empty data (Alex Williamson)" * tag 'vfio-v4.8-rc2' of git://github.com/awilliam/linux-vfio: vfio/pci: Fix NULL pointer oops in error interrupt setup handling
2 parents b112324 + c8952a7 commit f31494b

File tree

1 file changed

+49
-36
lines changed

1 file changed

+49
-36
lines changed

drivers/vfio/pci/vfio_pci_intrs.c

Lines changed: 49 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -564,67 +564,80 @@ static int vfio_pci_set_msi_trigger(struct vfio_pci_device *vdev,
564564
}
565565

566566
static int vfio_pci_set_ctx_trigger_single(struct eventfd_ctx **ctx,
567-
uint32_t flags, void *data)
567+
unsigned int count, uint32_t flags,
568+
void *data)
568569
{
569-
int32_t fd = *(int32_t *)data;
570-
571-
if (!(flags & VFIO_IRQ_SET_DATA_TYPE_MASK))
572-
return -EINVAL;
573-
574570
/* DATA_NONE/DATA_BOOL enables loopback testing */
575571
if (flags & VFIO_IRQ_SET_DATA_NONE) {
576-
if (*ctx)
577-
eventfd_signal(*ctx, 1);
578-
return 0;
572+
if (*ctx) {
573+
if (count) {
574+
eventfd_signal(*ctx, 1);
575+
} else {
576+
eventfd_ctx_put(*ctx);
577+
*ctx = NULL;
578+
}
579+
return 0;
580+
}
579581
} else if (flags & VFIO_IRQ_SET_DATA_BOOL) {
580-
uint8_t trigger = *(uint8_t *)data;
582+
uint8_t trigger;
583+
584+
if (!count)
585+
return -EINVAL;
586+
587+
trigger = *(uint8_t *)data;
581588
if (trigger && *ctx)
582589
eventfd_signal(*ctx, 1);
583-
return 0;
584-
}
585590

586-
/* Handle SET_DATA_EVENTFD */
587-
if (fd == -1) {
588-
if (*ctx)
589-
eventfd_ctx_put(*ctx);
590-
*ctx = NULL;
591591
return 0;
592-
} else if (fd >= 0) {
593-
struct eventfd_ctx *efdctx;
594-
efdctx = eventfd_ctx_fdget(fd);
595-
if (IS_ERR(efdctx))
596-
return PTR_ERR(efdctx);
597-
if (*ctx)
598-
eventfd_ctx_put(*ctx);
599-
*ctx = efdctx;
592+
} else if (flags & VFIO_IRQ_SET_DATA_EVENTFD) {
593+
int32_t fd;
594+
595+
if (!count)
596+
return -EINVAL;
597+
598+
fd = *(int32_t *)data;
599+
if (fd == -1) {
600+
if (*ctx)
601+
eventfd_ctx_put(*ctx);
602+
*ctx = NULL;
603+
} else if (fd >= 0) {
604+
struct eventfd_ctx *efdctx;
605+
606+
efdctx = eventfd_ctx_fdget(fd);
607+
if (IS_ERR(efdctx))
608+
return PTR_ERR(efdctx);
609+
610+
if (*ctx)
611+
eventfd_ctx_put(*ctx);
612+
613+
*ctx = efdctx;
614+
}
600615
return 0;
601-
} else
602-
return -EINVAL;
616+
}
617+
618+
return -EINVAL;
603619
}
604620

605621
static int vfio_pci_set_err_trigger(struct vfio_pci_device *vdev,
606622
unsigned index, unsigned start,
607623
unsigned count, uint32_t flags, void *data)
608624
{
609-
if (index != VFIO_PCI_ERR_IRQ_INDEX)
625+
if (index != VFIO_PCI_ERR_IRQ_INDEX || start != 0 || count > 1)
610626
return -EINVAL;
611627

612-
/*
613-
* We should sanitize start & count, but that wasn't caught
614-
* originally, so this IRQ index must forever ignore them :-(
615-
*/
616-
617-
return vfio_pci_set_ctx_trigger_single(&vdev->err_trigger, flags, data);
628+
return vfio_pci_set_ctx_trigger_single(&vdev->err_trigger,
629+
count, flags, data);
618630
}
619631

620632
static int vfio_pci_set_req_trigger(struct vfio_pci_device *vdev,
621633
unsigned index, unsigned start,
622634
unsigned count, uint32_t flags, void *data)
623635
{
624-
if (index != VFIO_PCI_REQ_IRQ_INDEX || start != 0 || count != 1)
636+
if (index != VFIO_PCI_REQ_IRQ_INDEX || start != 0 || count > 1)
625637
return -EINVAL;
626638

627-
return vfio_pci_set_ctx_trigger_single(&vdev->req_trigger, flags, data);
639+
return vfio_pci_set_ctx_trigger_single(&vdev->req_trigger,
640+
count, flags, data);
628641
}
629642

630643
int vfio_pci_set_irqs_ioctl(struct vfio_pci_device *vdev, uint32_t flags,

0 commit comments

Comments
 (0)