Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

+49 -36
+49 -36
drivers/vfio/pci/vfio_pci_intrs.c
··· 564 564 } 565 565 566 566 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) 568 569 { 569 - int32_t fd = *(int32_t *)data; 570 - 571 - if (!(flags & VFIO_IRQ_SET_DATA_TYPE_MASK)) 572 - return -EINVAL; 573 - 574 570 /* DATA_NONE/DATA_BOOL enables loopback testing */ 575 571 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 + } 579 581 } 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; 581 588 if (trigger && *ctx) 582 589 eventfd_signal(*ctx, 1); 590 + 591 + return 0; 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 + } 583 615 return 0; 584 616 } 585 617 586 - /* Handle SET_DATA_EVENTFD */ 587 - if (fd == -1) { 588 - if (*ctx) 589 - eventfd_ctx_put(*ctx); 590 - *ctx = NULL; 591 - 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; 600 - return 0; 601 - } else 602 - return -EINVAL; 618 + return -EINVAL; 603 619 } 604 620 605 621 static int vfio_pci_set_err_trigger(struct vfio_pci_device *vdev, 606 622 unsigned index, unsigned start, 607 623 unsigned count, uint32_t flags, void *data) 608 624 { 609 - if (index != VFIO_PCI_ERR_IRQ_INDEX) 625 + if (index != VFIO_PCI_ERR_IRQ_INDEX || start != 0 || count > 1) 610 626 return -EINVAL; 611 627 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); 618 630 } 619 631 620 632 static int vfio_pci_set_req_trigger(struct vfio_pci_device *vdev, 621 633 unsigned index, unsigned start, 622 634 unsigned count, uint32_t flags, void *data) 623 635 { 624 - if (index != VFIO_PCI_REQ_IRQ_INDEX || start != 0 || count != 1) 636 + if (index != VFIO_PCI_REQ_IRQ_INDEX || start != 0 || count > 1) 625 637 return -EINVAL; 626 638 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); 628 641 } 629 642 630 643 int vfio_pci_set_irqs_ioctl(struct vfio_pci_device *vdev, uint32_t flags,