All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jason Gunthorpe <jgg@nvidia.com>
To: Alex Williamson <alex.williamson@redhat.com>,
	Cornelia Huck <cohuck@redhat.com>,
	kvm@vger.kernel.org, Paolo Bonzini <pbonzini@redhat.com>
Cc: Eric Auger <eric.auger@redhat.com>,
	Christoph Hellwig <hch@lst.de>, Yi Liu <yi.l.liu@intel.com>
Subject: [PATCH 10/10] vfio/pci: Use the struct file as the handle not the vfio_group
Date: Thu, 14 Apr 2022 15:46:09 -0300	[thread overview]
Message-ID: <10-v1-33906a626da1+16b0-vfio_kvm_no_group_jgg@nvidia.com> (raw)
In-Reply-To: <0-v1-33906a626da1+16b0-vfio_kvm_no_group_jgg@nvidia.com>

VFIO PCI does a security check as part of hot reset to prove that the user
has permission to manipulate all the devices that will be impacted by the
reset.

Use a new API vfio_file_has_dev() to perform this security check against
the struct file directly and remove the vfio_group from VFIO PCI.

Since VFIO PCI was the last user of vfio_group_get_external_user() remove
it as well.

Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
---
 drivers/vfio/pci/vfio_pci_core.c | 43 +++++++++++-----------
 drivers/vfio/vfio.c              | 63 +++++++++-----------------------
 include/linux/vfio.h             |  2 +-
 3 files changed, 41 insertions(+), 67 deletions(-)

diff --git a/drivers/vfio/pci/vfio_pci_core.c b/drivers/vfio/pci/vfio_pci_core.c
index b7bb16f92ac628..ea584934683848 100644
--- a/drivers/vfio/pci/vfio_pci_core.c
+++ b/drivers/vfio/pci/vfio_pci_core.c
@@ -577,7 +577,7 @@ static int vfio_pci_fill_devs(struct pci_dev *pdev, void *data)
 
 struct vfio_pci_group_info {
 	int count;
-	struct vfio_group **groups;
+	struct file **files;
 };
 
 static bool vfio_pci_dev_below_slot(struct pci_dev *pdev, struct pci_slot *slot)
@@ -1039,10 +1039,10 @@ long vfio_pci_core_ioctl(struct vfio_device *core_vdev, unsigned int cmd,
 	} else if (cmd == VFIO_DEVICE_PCI_HOT_RESET) {
 		struct vfio_pci_hot_reset hdr;
 		int32_t *group_fds;
-		struct vfio_group **groups;
+		struct file **files;
 		struct vfio_pci_group_info info;
 		bool slot = false;
-		int group_idx, count = 0, ret = 0;
+		int file_idx, count = 0, ret = 0;
 
 		minsz = offsetofend(struct vfio_pci_hot_reset, count);
 
@@ -1075,17 +1075,17 @@ long vfio_pci_core_ioctl(struct vfio_device *core_vdev, unsigned int cmd,
 			return -EINVAL;
 
 		group_fds = kcalloc(hdr.count, sizeof(*group_fds), GFP_KERNEL);
-		groups = kcalloc(hdr.count, sizeof(*groups), GFP_KERNEL);
-		if (!group_fds || !groups) {
+		files = kcalloc(hdr.count, sizeof(*files), GFP_KERNEL);
+		if (!group_fds || !files) {
 			kfree(group_fds);
-			kfree(groups);
+			kfree(files);
 			return -ENOMEM;
 		}
 
 		if (copy_from_user(group_fds, (void __user *)(arg + minsz),
 				   hdr.count * sizeof(*group_fds))) {
 			kfree(group_fds);
-			kfree(groups);
+			kfree(files);
 			return -EFAULT;
 		}
 
@@ -1094,22 +1094,23 @@ long vfio_pci_core_ioctl(struct vfio_device *core_vdev, unsigned int cmd,
 		 * user interface and store the group and iommu ID.  This
 		 * ensures the group is held across the reset.
 		 */
-		for (group_idx = 0; group_idx < hdr.count; group_idx++) {
-			struct vfio_group *group;
-			struct fd f = fdget(group_fds[group_idx]);
-			if (!f.file) {
+		for (file_idx = 0; file_idx < hdr.count; file_idx++) {
+			struct file *file = fget(group_fds[file_idx]);
+			const struct vfio_file_ops *ops;
+
+			if (!file) {
 				ret = -EBADF;
 				break;
 			}
 
-			group = vfio_group_get_external_user(f.file);
-			fdput(f);
-			if (IS_ERR(group)) {
-				ret = PTR_ERR(group);
+			ops = vfio_file_get_ops(file);
+			if (IS_ERR(ops)) {
+				fput(file);
+				ret = PTR_ERR(ops);
 				break;
 			}
 
-			groups[group_idx] = group;
+			files[file_idx] = file;
 		}
 
 		kfree(group_fds);
@@ -1119,15 +1120,15 @@ long vfio_pci_core_ioctl(struct vfio_device *core_vdev, unsigned int cmd,
 			goto hot_reset_release;
 
 		info.count = hdr.count;
-		info.groups = groups;
+		info.files = files;
 
 		ret = vfio_pci_dev_set_hot_reset(vdev->vdev.dev_set, &info);
 
 hot_reset_release:
-		for (group_idx--; group_idx >= 0; group_idx--)
-			vfio_group_put_external_user(groups[group_idx]);
+		for (file_idx--; file_idx >= 0; file_idx--)
+			fput(files[file_idx]);
 
-		kfree(groups);
+		kfree(files);
 		return ret;
 	} else if (cmd == VFIO_DEVICE_IOEVENTFD) {
 		struct vfio_device_ioeventfd ioeventfd;
@@ -1964,7 +1965,7 @@ static bool vfio_dev_in_groups(struct vfio_pci_core_device *vdev,
 	unsigned int i;
 
 	for (i = 0; i < groups->count; i++)
-		if (groups->groups[i] == vdev->vdev.group)
+		if (vfio_file_has_dev(groups->files[i], &vdev->vdev))
 			return true;
 	return false;
 }
diff --git a/drivers/vfio/vfio.c b/drivers/vfio/vfio.c
index 2eb63d9dded8fb..69772105ec43e8 100644
--- a/drivers/vfio/vfio.c
+++ b/drivers/vfio/vfio.c
@@ -1899,51 +1899,6 @@ static const struct file_operations vfio_device_fops = {
 	.mmap		= vfio_device_fops_mmap,
 };
 
-/*
- * External user API, exported by symbols to be linked dynamically.
- *
- * The protocol includes:
- *  1. do normal VFIO init operation:
- *	- opening a new container;
- *	- attaching group(s) to it;
- *	- setting an IOMMU driver for a container.
- * When IOMMU is set for a container, all groups in it are
- * considered ready to use by an external user.
- *
- * 2. User space passes a group fd to an external user.
- * The external user calls vfio_group_get_external_user()
- * to verify that:
- *	- the group is initialized;
- *	- IOMMU is set for it.
- * If both checks passed, vfio_group_get_external_user()
- * increments the container user counter to prevent
- * the VFIO group from disposal before KVM exits.
- *
- * 3. When the external KVM finishes, it calls
- * vfio_group_put_external_user() to release the VFIO group.
- * This call decrements the container user counter.
- */
-struct vfio_group *vfio_group_get_external_user(struct file *filep)
-{
-	struct vfio_group *group = filep->private_data;
-	int ret;
-
-	if (filep->f_op != &vfio_group_fops)
-		return ERR_PTR(-EINVAL);
-
-	ret = vfio_group_add_container_user(group);
-	if (ret)
-		return ERR_PTR(ret);
-
-	/*
-	 * Since the caller holds the fget on the file group->users must be >= 1
-	 */
-	vfio_group_get(group);
-
-	return group;
-}
-EXPORT_SYMBOL_GPL(vfio_group_get_external_user);
-
 /*
  * External user API, exported by symbols to be linked dynamically.
  * The external user passes in a device pointer
@@ -2068,6 +2023,24 @@ const struct vfio_file_ops *vfio_file_get_ops(struct file *filep)
 }
 EXPORT_SYMBOL_GPL(vfio_file_get_ops);
 
+/**
+ * vfio_file_has_dev - True if the VFIO file is a handle for device
+ * @filep: VFIO file to check
+ * @device: Device that must be part of the file
+ *
+ * Returns true if given file has permission to manipulate the given device.
+ */
+bool vfio_file_has_dev(struct file *filep, struct vfio_device *device)
+{
+	struct vfio_group *group = filep->private_data;
+
+	if (filep->f_op != &vfio_group_fops)
+		return false;
+
+	return group == device->group;
+}
+EXPORT_SYMBOL_GPL(vfio_file_has_dev);
+
 /*
  * Sub-module support
  */
diff --git a/include/linux/vfio.h b/include/linux/vfio.h
index bc6e47f3f26560..ea254283fa0522 100644
--- a/include/linux/vfio.h
+++ b/include/linux/vfio.h
@@ -145,11 +145,11 @@ struct vfio_file_ops {
 	bool (*is_enforced_coherent)(struct file *filep);
 	void (*set_kvm)(struct file *filep, struct kvm *kvm);
 };
-extern struct vfio_group *vfio_group_get_external_user(struct file *filep);
 extern void vfio_group_put_external_user(struct vfio_group *group);
 extern struct vfio_group *vfio_group_get_external_user_from_dev(struct device
 								*dev);
 const struct vfio_file_ops *vfio_file_get_ops(struct file *filep);
+bool vfio_file_has_dev(struct file *filep, struct vfio_device *device);
 
 #define VFIO_PIN_PAGES_MAX_ENTRIES	(PAGE_SIZE/sizeof(unsigned long))
 
-- 
2.35.1


      parent reply	other threads:[~2022-04-14 18:46 UTC|newest]

Thread overview: 47+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-04-14 18:45 [PATCH 00/10] Remove vfio_group from the struct file facing VFIO API Jason Gunthorpe
2022-04-14 18:46 ` [PATCH 01/10] kvm/vfio: Move KVM_DEV_VFIO_GROUP_* ioctls into functions Jason Gunthorpe
2022-04-15  3:36   ` Tian, Kevin
2022-04-15  7:18   ` Christoph Hellwig
2022-04-14 18:46 ` [PATCH 02/10] kvm/vfio: Reduce the scope of PPC #ifdefs Jason Gunthorpe
2022-04-15  4:47   ` Christoph Hellwig
2022-04-15 12:13     ` Jason Gunthorpe
2022-04-15 12:35       ` Jason Gunthorpe
2022-04-15 14:36         ` Christoph Hellwig
2022-04-14 18:46 ` [PATCH 03/10] kvm/vfio: Store the struct file in the kvm_vfio_group Jason Gunthorpe
2022-04-15  3:44   ` Tian, Kevin
2022-04-15 22:24     ` Jason Gunthorpe
2022-04-15  7:20   ` Christoph Hellwig
2022-04-19 19:24     ` Jason Gunthorpe
2022-04-14 18:46 ` [PATCH 04/10] vfio: Use a struct of function pointers instead of a many symbol_get()'s Jason Gunthorpe
2022-04-15  3:57   ` Tian, Kevin
2022-04-15 21:54     ` Jason Gunthorpe
2022-04-16  0:00       ` Tian, Kevin
2022-04-16  1:33         ` Jason Gunthorpe
2022-04-18  3:56           ` Tian, Kevin
2022-04-19 12:16             ` Jason Gunthorpe
2022-04-15  4:45   ` Christoph Hellwig
2022-04-15 12:13     ` Jason Gunthorpe
2022-04-15 14:36       ` Christoph Hellwig
2022-04-15 15:31         ` Jason Gunthorpe
2022-04-14 18:46 ` [PATCH 05/10] vfio: Move vfio_external_user_iommu_id() to vfio_file_ops Jason Gunthorpe
2022-04-15  3:59   ` Tian, Kevin
2022-04-15  7:31   ` Christoph Hellwig
2022-04-15 12:25     ` Jason Gunthorpe
2022-04-15 14:37       ` Christoph Hellwig
2022-04-14 18:46 ` [PATCH 06/10] vfio: Remove vfio_external_group_match_file() Jason Gunthorpe
2022-04-15  4:02   ` Tian, Kevin
2022-04-15  7:32   ` Christoph Hellwig
2022-04-14 18:46 ` [PATCH 07/10] vfio: Move vfio_external_check_extension() to vfio_file_ops Jason Gunthorpe
2022-04-15  4:07   ` Tian, Kevin
2022-04-19 19:23     ` Jason Gunthorpe
2022-04-20  3:05       ` Tian, Kevin
2022-04-15  4:48   ` Christoph Hellwig
2022-04-14 18:46 ` [PATCH 08/10] vfio: Move vfio_group_set_kvm() into vfio_file_ops Jason Gunthorpe
2022-04-15  4:09   ` Tian, Kevin
2022-04-14 18:46 ` [PATCH 09/10] kvm/vfio: Remove vfio_group from kvm Jason Gunthorpe
2022-04-15  4:21   ` Tian, Kevin
2022-04-15 21:56     ` Jason Gunthorpe
2022-04-16  0:42       ` Tian, Kevin
2022-04-16  1:34         ` Jason Gunthorpe
2022-04-18  6:09           ` Tian, Kevin
2022-04-14 18:46 ` Jason Gunthorpe [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=10-v1-33906a626da1+16b0-vfio_kvm_no_group_jgg@nvidia.com \
    --to=jgg@nvidia.com \
    --cc=alex.williamson@redhat.com \
    --cc=cohuck@redhat.com \
    --cc=eric.auger@redhat.com \
    --cc=hch@lst.de \
    --cc=kvm@vger.kernel.org \
    --cc=pbonzini@redhat.com \
    --cc=yi.l.liu@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.