Commit 0289a67cd70b for kernel

commit 0289a67cd70bf9d3807e289f4efd643e16a6c6b4
Author: Stanislav Kinsburskii <skinsburskii@linux.microsoft.com>
Date:   Thu May 7 15:43:43 2026 +0000

    mshv: Fix level-triggered check on uninitialized data

    In mshv_irqfd_assign(), the level-triggered validation for resample
    irqfds checks irqfd_lapic_irq.lapic_control.level_triggered before
    mshv_irqfd_update() has populated the field. Since the irqfd struct is
    zero-allocated, level_triggered is always 0 at that point, causing the
    check to always reject resample irqfds with -EINVAL. This makes
    level-triggered interrupt resampling — used to avoid interrupt storms
    with assigned devices — completely non-functional.

    Move the check after the mshv_irqfd_update() call, which resolves the
    IRQ routing entry and populates irqfd_lapic_irq with the actual trigger
    mode.

    Fixes: 621191d709b14 ("Drivers: hv: Introduce mshv_root module to expose /dev/mshv to VMMs")
    Signed-off-by: Stanislav Kinsburskii <skinsburskii@linux.microsoft.com>
    Reviewed-by: Anirudh Rayabharam (Microsoft) <anirudh@anirudhrb.com>
    Signed-off-by: Wei Liu <wei.liu@kernel.org>

diff --git a/drivers/hv/mshv_eventfd.c b/drivers/hv/mshv_eventfd.c
index 5995a62aff8d..047e5bd43238 100644
--- a/drivers/hv/mshv_eventfd.c
+++ b/drivers/hv/mshv_eventfd.c
@@ -473,6 +473,19 @@ static int mshv_irqfd_assign(struct mshv_partition *pt,
 	init_poll_funcptr(&irqfd->irqfd_polltbl, mshv_irqfd_queue_proc);

 	spin_lock_irq(&pt->pt_irqfds_lock);
+	ret = 0;
+	hlist_for_each_entry(tmp, &pt->pt_irqfds_list, irqfd_hnode) {
+		if (irqfd->irqfd_eventfd_ctx != tmp->irqfd_eventfd_ctx)
+			continue;
+		/* This fd is used for another irq already. */
+		ret = -EBUSY;
+		spin_unlock_irq(&pt->pt_irqfds_lock);
+		goto fail;
+	}
+
+	idx = srcu_read_lock(&pt->pt_irq_srcu);
+	mshv_irqfd_update(pt, irqfd);
+
 #if IS_ENABLED(CONFIG_X86)
 	if (args->flags & BIT(MSHV_IRQFD_BIT_RESAMPLE) &&
 	    !irqfd->irqfd_lapic_irq.lapic_control.level_triggered) {
@@ -481,22 +494,12 @@ static int mshv_irqfd_assign(struct mshv_partition *pt,
 		 * Otherwise return with failure
 		 */
 		spin_unlock_irq(&pt->pt_irqfds_lock);
+		srcu_read_unlock(&pt->pt_irq_srcu, idx);
 		ret = -EINVAL;
 		goto fail;
 	}
 #endif
-	ret = 0;
-	hlist_for_each_entry(tmp, &pt->pt_irqfds_list, irqfd_hnode) {
-		if (irqfd->irqfd_eventfd_ctx != tmp->irqfd_eventfd_ctx)
-			continue;
-		/* This fd is used for another irq already. */
-		ret = -EBUSY;
-		spin_unlock_irq(&pt->pt_irqfds_lock);
-		goto fail;
-	}

-	idx = srcu_read_lock(&pt->pt_irq_srcu);
-	mshv_irqfd_update(pt, irqfd);
 	hlist_add_head(&irqfd->irqfd_hnode, &pt->pt_irqfds_list);
 	spin_unlock_irq(&pt->pt_irqfds_lock);