From: Sean Christopherson <seanjc@google.com> mainline inclusion from mainline-v6.17 commit 23b54381cee2928e8b5622e654ca4516f30d2f1a category: bugfix bugzilla: https://atomgit.com/openeuler/kernel/issues/9782 CVE: NA Reference: https://github.com/kvm-x86/linux/commit/23b54381cee2 -------------------------------- Pass in the Linux IRQ associated with an IRQ bypass producer instead of relying on the caller to set the field prior to registration, as there's no benefit to relying on callers to do the right thing. Take care to set producer->irq before __connect(), as KVM expects the IRQ to be valid as soon as a connection is possible. Provides additional adaptation for the ub vfio device in openEuler. Reviewed-by: Kevin Tian <kevin.tian@intel.com> Reviewed-by: Alex Williamson <alex.williamson@redhat.com> Acked-by: Michael S. Tsirkin <mst@redhat.com> Link: https://lore.kernel.org/r/20250516230734.2564775-9-seanjc@google.com Signed-off-by: Sean Christopherson <seanjc@google.com> Signed-off-by: Qiqi Li <liqiqi23@huawei.com> --- drivers/vfio/pci/vfio_pci_intrs.c | 3 +-- drivers/vfio/ubus/vfio_ub_intrs.c | 3 ++- drivers/vhost/vdpa.c | 4 ++-- include/linux/irqbypass.h | 2 +- virt/lib/irqbypass.c | 5 ++++- 5 files changed, 10 insertions(+), 7 deletions(-) diff --git a/drivers/vfio/pci/vfio_pci_intrs.c b/drivers/vfio/pci/vfio_pci_intrs.c index 3f881cb44245..557e31150d6b 100644 --- a/drivers/vfio/pci/vfio_pci_intrs.c +++ b/drivers/vfio/pci/vfio_pci_intrs.c @@ -518,8 +518,7 @@ static int vfio_msi_set_vector_signal(struct vfio_pci_core_device *vdev, if (ret) goto out_put_eventfd_ctx; - ctx->producer.irq = irq; - ret = irq_bypass_register_producer(&ctx->producer, trigger); + ret = irq_bypass_register_producer(&ctx->producer, trigger, irq); if (unlikely(ret)) { dev_info(&pdev->dev, "irq bypass producer (eventfd %p) registration fails: %d\n", diff --git a/drivers/vfio/ubus/vfio_ub_intrs.c b/drivers/vfio/ubus/vfio_ub_intrs.c index 5159f5c54474..dfc9528d37ba 100644 --- a/drivers/vfio/ubus/vfio_ub_intrs.c +++ b/drivers/vfio/ubus/vfio_ub_intrs.c @@ -116,7 +116,8 @@ static int vfio_ub_intr_set_vector_signal(struct vfio_ub_core_device *vdev, goto err_irq; vdev->ctx[vector].producer.irq = irq_vec; - ret = irq_bypass_register_producer(&vdev->ctx[vector].producer, trigger); + ret = irq_bypass_register_producer(&vdev->ctx[vector].producer, + trigger, irq_vec); if (unlikely(ret)) ub_info(uent, "irq bypass producer registration failed, ret=%d\n", ret); vdev->ctx[vector].trigger = trigger; diff --git a/drivers/vhost/vdpa.c b/drivers/vhost/vdpa.c index 781249c5f41d..0583374602f8 100644 --- a/drivers/vhost/vdpa.c +++ b/drivers/vhost/vdpa.c @@ -200,8 +200,8 @@ static void vhost_vdpa_setup_vq_irq(struct vhost_vdpa *v, u16 qid) if (!vq->call_ctx.ctx) return; - vq->call_ctx.producer.irq = irq; - ret = irq_bypass_register_producer(&vq->call_ctx.producer, vq->call_ctx.ctx); + ret = irq_bypass_register_producer(&vq->call_ctx.producer, + vq->call_ctx.ctx, irq); if (unlikely(ret)) dev_info(&v->dev, "vq %u, irq bypass producer (eventfd %p) registration fails, ret = %d\n", qid, vq->call_ctx.ctx, ret); diff --git a/include/linux/irqbypass.h b/include/linux/irqbypass.h index cd64fcaa88fe..ede1fa938152 100644 --- a/include/linux/irqbypass.h +++ b/include/linux/irqbypass.h @@ -84,7 +84,7 @@ struct irq_bypass_consumer { }; int irq_bypass_register_producer(struct irq_bypass_producer *producer, - struct eventfd_ctx *eventfd); + struct eventfd_ctx *eventfd, int irq); void irq_bypass_unregister_producer(struct irq_bypass_producer *producer); int irq_bypass_register_consumer(struct irq_bypass_consumer *consumer, struct eventfd_ctx *eventfd); diff --git a/virt/lib/irqbypass.c b/virt/lib/irqbypass.c index ea888b9203d2..62c160200be9 100644 --- a/virt/lib/irqbypass.c +++ b/virt/lib/irqbypass.c @@ -85,12 +85,13 @@ static void __disconnect(struct irq_bypass_producer *prod, * irq_bypass_register_producer - register IRQ bypass producer * @producer: pointer to producer structure * @eventfd: pointer to the eventfd context associated with the producer + * @irq: Linux IRQ number of the underlying producer device * * Add the provided IRQ producer to the set of producers and connect with the * consumer with a matching eventfd, if one exists. */ int irq_bypass_register_producer(struct irq_bypass_producer *producer, - struct eventfd_ctx *eventfd) + struct eventfd_ctx *eventfd, int irq) { unsigned long index = (unsigned long)eventfd; struct irq_bypass_consumer *consumer; @@ -99,6 +100,8 @@ int irq_bypass_register_producer(struct irq_bypass_producer *producer, if (WARN_ON_ONCE(producer->eventfd)) return -EINVAL; + producer->irq = irq; + guard(mutex)(&lock); ret = xa_insert(&producers, index, producer, GFP_KERNEL); -- 2.43.0