Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f31494bd authored by Linus Torvalds's avatar Linus Torvalds
Browse files

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
parents b112324c c8952a70
Loading
Loading
Loading
Loading
+49 −36
Original line number Diff line number Diff line
@@ -564,41 +564,57 @@ static int vfio_pci_set_msi_trigger(struct vfio_pci_device *vdev,
}

static int vfio_pci_set_ctx_trigger_single(struct eventfd_ctx **ctx,
					   uint32_t flags, void *data)
					   unsigned int count, uint32_t flags,
					   void *data)
{
	int32_t fd = *(int32_t *)data;

	if (!(flags & VFIO_IRQ_SET_DATA_TYPE_MASK))
		return -EINVAL;

	/* DATA_NONE/DATA_BOOL enables loopback testing */
	if (flags & VFIO_IRQ_SET_DATA_NONE) {
		if (*ctx)
		if (*ctx) {
			if (count) {
				eventfd_signal(*ctx, 1);
			} else {
				eventfd_ctx_put(*ctx);
				*ctx = NULL;
			}
			return 0;
		}
	} else if (flags & VFIO_IRQ_SET_DATA_BOOL) {
		uint8_t trigger = *(uint8_t *)data;
		uint8_t trigger;

		if (!count)
			return -EINVAL;

		trigger = *(uint8_t *)data;
		if (trigger && *ctx)
			eventfd_signal(*ctx, 1);

		return 0;
	}
	} else if (flags & VFIO_IRQ_SET_DATA_EVENTFD) {
		int32_t fd;

		if (!count)
			return -EINVAL;

	/* Handle SET_DATA_EVENTFD */
		fd = *(int32_t *)data;
		if (fd == -1) {
			if (*ctx)
				eventfd_ctx_put(*ctx);
			*ctx = NULL;
		return 0;
		} else if (fd >= 0) {
			struct eventfd_ctx *efdctx;

			efdctx = eventfd_ctx_fdget(fd);
			if (IS_ERR(efdctx))
				return PTR_ERR(efdctx);

			if (*ctx)
				eventfd_ctx_put(*ctx);

			*ctx = efdctx;
		}
		return 0;
	} else
	}

	return -EINVAL;
}

@@ -606,25 +622,22 @@ static int vfio_pci_set_err_trigger(struct vfio_pci_device *vdev,
				    unsigned index, unsigned start,
				    unsigned count, uint32_t flags, void *data)
{
	if (index != VFIO_PCI_ERR_IRQ_INDEX)
	if (index != VFIO_PCI_ERR_IRQ_INDEX || start != 0 || count > 1)
		return -EINVAL;

	/*
	 * We should sanitize start & count, but that wasn't caught
	 * originally, so this IRQ index must forever ignore them :-(
	 */

	return vfio_pci_set_ctx_trigger_single(&vdev->err_trigger, flags, data);
	return vfio_pci_set_ctx_trigger_single(&vdev->err_trigger,
					       count, flags, data);
}

static int vfio_pci_set_req_trigger(struct vfio_pci_device *vdev,
				    unsigned index, unsigned start,
				    unsigned count, uint32_t flags, void *data)
{
	if (index != VFIO_PCI_REQ_IRQ_INDEX || start != 0 || count != 1)
	if (index != VFIO_PCI_REQ_IRQ_INDEX || start != 0 || count > 1)
		return -EINVAL;

	return vfio_pci_set_ctx_trigger_single(&vdev->req_trigger, flags, data);
	return vfio_pci_set_ctx_trigger_single(&vdev->req_trigger,
					       count, flags, data);
}

int vfio_pci_set_irqs_ioctl(struct vfio_pci_device *vdev, uint32_t flags,