Skip to content
This repository was archived by the owner on Oct 31, 2024. It is now read-only.

Commit ca64edd

Browse files
jasowanggregkh
authored andcommitted
vhost_vdpa: assign irq bypass producer token correctly
[ Upstream commit 02e9e93 ] We used to call irq_bypass_unregister_producer() in vhost_vdpa_setup_vq_irq() which is problematic as we don't know if the token pointer is still valid or not. Actually, we use the eventfd_ctx as the token so the life cycle of the token should be bound to the VHOST_SET_VRING_CALL instead of vhost_vdpa_setup_vq_irq() which could be called by set_status(). Fixing this by setting up irq bypass producer's token when handling VHOST_SET_VRING_CALL and un-registering the producer before calling vhost_vring_ioctl() to prevent a possible use after free as eventfd could have been released in vhost_vring_ioctl(). And such registering and unregistering will only be done if DRIVER_OK is set. Reported-by: Dragos Tatulea <dtatulea@nvidia.com> Tested-by: Dragos Tatulea <dtatulea@nvidia.com> Reviewed-by: Dragos Tatulea <dtatulea@nvidia.com> Fixes: 2cf1ba9 ("vhost_vdpa: implement IRQ offloading in vhost_vdpa") Signed-off-by: Jason Wang <jasowang@redhat.com> Message-Id: <20240816031900.18013-1-jasowang@redhat.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Sasha Levin <sashal@kernel.org>
1 parent 70a180b commit ca64edd

File tree

1 file changed

+13
-3
lines changed

1 file changed

+13
-3
lines changed

drivers/vhost/vdpa.c

+13-3
Original file line numberDiff line numberDiff line change
@@ -191,11 +191,9 @@ static void vhost_vdpa_setup_vq_irq(struct vhost_vdpa *v, u16 qid)
191191
if (irq < 0)
192192
return;
193193

194-
irq_bypass_unregister_producer(&vq->call_ctx.producer);
195194
if (!vq->call_ctx.ctx)
196195
return;
197196

198-
vq->call_ctx.producer.token = vq->call_ctx.ctx;
199197
vq->call_ctx.producer.irq = irq;
200198
ret = irq_bypass_register_producer(&vq->call_ctx.producer);
201199
if (unlikely(ret))
@@ -627,6 +625,14 @@ static long vhost_vdpa_vring_ioctl(struct vhost_vdpa *v, unsigned int cmd,
627625
vq->last_avail_idx = vq_state.split.avail_index;
628626
}
629627
break;
628+
case VHOST_SET_VRING_CALL:
629+
if (vq->call_ctx.ctx) {
630+
if (ops->get_status(vdpa) &
631+
VIRTIO_CONFIG_S_DRIVER_OK)
632+
vhost_vdpa_unsetup_vq_irq(v, idx);
633+
vq->call_ctx.producer.token = NULL;
634+
}
635+
break;
630636
}
631637

632638
r = vhost_vring_ioctl(&v->vdev, cmd, argp);
@@ -659,13 +665,16 @@ static long vhost_vdpa_vring_ioctl(struct vhost_vdpa *v, unsigned int cmd,
659665
cb.callback = vhost_vdpa_virtqueue_cb;
660666
cb.private = vq;
661667
cb.trigger = vq->call_ctx.ctx;
668+
vq->call_ctx.producer.token = vq->call_ctx.ctx;
669+
if (ops->get_status(vdpa) &
670+
VIRTIO_CONFIG_S_DRIVER_OK)
671+
vhost_vdpa_setup_vq_irq(v, idx);
662672
} else {
663673
cb.callback = NULL;
664674
cb.private = NULL;
665675
cb.trigger = NULL;
666676
}
667677
ops->set_vq_cb(vdpa, idx, &cb);
668-
vhost_vdpa_setup_vq_irq(v, idx);
669678
break;
670679

671680
case VHOST_SET_VRING_NUM:
@@ -1316,6 +1325,7 @@ static int vhost_vdpa_open(struct inode *inode, struct file *filep)
13161325
for (i = 0; i < nvqs; i++) {
13171326
vqs[i] = &v->vqs[i];
13181327
vqs[i]->handle_kick = handle_vq_kick;
1328+
vqs[i]->call_ctx.ctx = NULL;
13191329
}
13201330
vhost_dev_init(dev, vqs, nvqs, 0, 0, 0, false,
13211331
vhost_vdpa_process_iotlb_msg);

0 commit comments

Comments
 (0)