Commit 72e3b0311aa9 for kernel

commit 72e3b0311aa90568a4b42a64445d1d3e1dc5a34d
Author: Stanislav Kinsburskii <skinsburskii@linux.microsoft.com>
Date:   Thu May 7 15:44:32 2026 +0000

    mshv: Publish VP to pt_vp_array before installing the file descriptor

    mshv_partition_ioctl_create_vp() called anon_inode_getfd() before
    publishing the new VP into partition->pt_vp_array.  anon_inode_getfd()
    includes fd_install(), so the fd was live in current->files before the
    publish ran.

    A concurrent MSHV_RUN_VP ioctl on that fd does not serialise against the
    in-progress MSHV_CREATE_VP — it takes vp->vp_mutex, not the partition
    mutex.  Once the VP starts running and traps, mshv_intercept_isr() can look
    up partition->pt_vp_array[vp_index] and observe NULL, silently dropping the
    intercept message.

    Split the fd creation: reserve an fd with get_unused_fd_flags(), create the
    file with anon_inode_getfile(), publish the VP via smp_store_release(), and
    finally call fd_install() as the userspace-visibility commit point.

    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_root_main.c b/drivers/hv/mshv_root_main.c
index 8a15448e2ace..cc2cfce2aefd 100644
--- a/drivers/hv/mshv_root_main.c
+++ b/drivers/hv/mshv_root_main.c
@@ -1072,6 +1072,8 @@ mshv_partition_ioctl_create_vp(struct mshv_partition *partition,
 	struct mshv_vp *vp;
 	struct page *intercept_msg_page, *register_page, *ghcb_page;
 	struct hv_stats_page *stats_pages[2];
+	struct file *file;
+	int fd;
 	long ret;

 	if (copy_from_user(&args, arg, sizeof(args)))
@@ -1146,14 +1148,18 @@ mshv_partition_ioctl_create_vp(struct mshv_partition *partition,
 	if (ret)
 		goto put_partition;

-	/*
-	 * Keep anon_inode_getfd last: it installs fd in the file struct and
-	 * thus makes the state accessible in user space.
-	 */
-	ret = anon_inode_getfd("mshv_vp", &mshv_vp_fops, vp,
-			       O_RDWR | O_CLOEXEC);
-	if (ret < 0)
+	fd = get_unused_fd_flags(O_RDWR | O_CLOEXEC);
+	if (fd < 0) {
+		ret = fd;
 		goto remove_debugfs_vp;
+	}
+
+	file = anon_inode_getfile("mshv_vp", &mshv_vp_fops, vp,
+				  O_RDWR | O_CLOEXEC);
+	if (IS_ERR(file)) {
+		ret = PTR_ERR(file);
+		goto put_unused_vp_fd;
+	}

 	/* already exclusive with the partition mutex for all ioctls */
 	partition->pt_vp_count++;
@@ -1165,8 +1171,17 @@ mshv_partition_ioctl_create_vp(struct mshv_partition *partition,
 	 */
 	smp_store_release(&partition->pt_vp_array[args.vp_index], vp);

+	/*
+	 * fd_install() is the userspace-visibility commit point.  Must be the
+	 * last operation that can fail or be observed.
+	 */
+	fd_install(fd, file);
+	ret = fd;
+
 	goto out;

+put_unused_vp_fd:
+	put_unused_fd(fd);
 remove_debugfs_vp:
 	mshv_debugfs_vp_remove(vp);
 put_partition: