Commit f31494bd authored by Linus Torvalds's avatar Linus Torvalds

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
...@@ -564,67 +564,80 @@ static int vfio_pci_set_msi_trigger(struct vfio_pci_device *vdev, ...@@ -564,67 +564,80 @@ static int vfio_pci_set_msi_trigger(struct vfio_pci_device *vdev,
} }
static int vfio_pci_set_ctx_trigger_single(struct eventfd_ctx **ctx, 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 */ /* DATA_NONE/DATA_BOOL enables loopback testing */
if (flags & VFIO_IRQ_SET_DATA_NONE) { if (flags & VFIO_IRQ_SET_DATA_NONE) {
if (*ctx) if (*ctx) {
eventfd_signal(*ctx, 1); if (count) {
return 0; eventfd_signal(*ctx, 1);
} else {
eventfd_ctx_put(*ctx);
*ctx = NULL;
}
return 0;
}
} else if (flags & VFIO_IRQ_SET_DATA_BOOL) { } 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) if (trigger && *ctx)
eventfd_signal(*ctx, 1); eventfd_signal(*ctx, 1);
return 0;
}
/* Handle SET_DATA_EVENTFD */
if (fd == -1) {
if (*ctx)
eventfd_ctx_put(*ctx);
*ctx = NULL;
return 0; return 0;
} else if (fd >= 0) { } else if (flags & VFIO_IRQ_SET_DATA_EVENTFD) {
struct eventfd_ctx *efdctx; int32_t fd;
efdctx = eventfd_ctx_fdget(fd);
if (IS_ERR(efdctx)) if (!count)
return PTR_ERR(efdctx); return -EINVAL;
if (*ctx)
eventfd_ctx_put(*ctx); fd = *(int32_t *)data;
*ctx = efdctx; if (fd == -1) {
if (*ctx)
eventfd_ctx_put(*ctx);
*ctx = NULL;
} 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; return 0;
} else }
return -EINVAL;
return -EINVAL;
} }
static int vfio_pci_set_err_trigger(struct vfio_pci_device *vdev, static int vfio_pci_set_err_trigger(struct vfio_pci_device *vdev,
unsigned index, unsigned start, unsigned index, unsigned start,
unsigned count, uint32_t flags, void *data) 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; return -EINVAL;
/* return vfio_pci_set_ctx_trigger_single(&vdev->err_trigger,
* We should sanitize start & count, but that wasn't caught count, flags, data);
* originally, so this IRQ index must forever ignore them :-(
*/
return vfio_pci_set_ctx_trigger_single(&vdev->err_trigger, flags, data);
} }
static int vfio_pci_set_req_trigger(struct vfio_pci_device *vdev, static int vfio_pci_set_req_trigger(struct vfio_pci_device *vdev,
unsigned index, unsigned start, unsigned index, unsigned start,
unsigned count, uint32_t flags, void *data) 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 -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, int vfio_pci_set_irqs_ioctl(struct vfio_pci_device *vdev, uint32_t flags,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment