mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Xu Yilun <yilun.xu@linux.intel.com>
To: jgg@nvidia.com, jgg@ziepe.ca, kevin.tian@intel.com,
	will@kernel.org, aneesh.kumar@kernel.org
Cc: iommu@lists.linux.dev, linux-kernel@vger.kernel.org,
	joro@8bytes.org, robin.murphy@arm.com, shuah@kernel.org,
	nicolinc@nvidia.com, aik@amd.com, dan.j.williams@intel.com,
	baolu.lu@linux.intel.com, yilun.xu@linux.intel.com,
	yilun.xu@intel.com
Subject: [PATCH v2 1/4] iommufd: Add iommufd_object_tombstone_user() helper
Date: Mon, 23 Jun 2025 17:49:43 +0800	[thread overview]
Message-ID: <20250623094946.1714996-2-yilun.xu@linux.intel.com> (raw)
In-Reply-To: <20250623094946.1714996-1-yilun.xu@linux.intel.com>

Add the iommufd_object_tombstone_user() helper, which allows the caller
to destroy an iommufd object created by userspace.

This is useful on some destroy paths when the kernel caller finds the
object should have been removed by userspace but is still alive. With
this helper, the caller destroys the object but leave the object ID
reserved (so called tombstone). The tombstone prevents repurposing the
object ID without awareness from the original user.

Since this happens for abnomal userspace behavior, for simplicity, the
tombstoned object ID would be permanently leaked until
iommufd_fops_release(). I.e. the original user gets an error when
calling ioctl(IOMMU_DESTROY) on that ID.

The first use case would be to ensure the iommufd_vdevice can't outlive
the associated iommufd_device.

Suggested-by: Jason Gunthorpe <jgg@nvidia.com>
Signed-off-by: Xu Yilun <yilun.xu@linux.intel.com>
---
 drivers/iommu/iommufd/iommufd_private.h | 23 +++++++++++++++++-
 drivers/iommu/iommufd/main.c            | 31 ++++++++++++++++++-------
 2 files changed, 45 insertions(+), 9 deletions(-)

diff --git a/drivers/iommu/iommufd/iommufd_private.h b/drivers/iommu/iommufd/iommufd_private.h
index 9ccc83341f32..fbc9ef78d81f 100644
--- a/drivers/iommu/iommufd/iommufd_private.h
+++ b/drivers/iommu/iommufd/iommufd_private.h
@@ -187,7 +187,8 @@ void iommufd_object_finalize(struct iommufd_ctx *ictx,
 			     struct iommufd_object *obj);
 
 enum {
-	REMOVE_WAIT_SHORTTERM = 1,
+	REMOVE_WAIT_SHORTTERM	= BIT(0),
+	REMOVE_OBJ_TOMBSTONE	= BIT(1),
 };
 int iommufd_object_remove(struct iommufd_ctx *ictx,
 			  struct iommufd_object *to_destroy, u32 id,
@@ -213,6 +214,26 @@ static inline void iommufd_object_destroy_user(struct iommufd_ctx *ictx,
 	WARN_ON(ret);
 }
 
+/*
+ * Similar to iommufd_object_destroy_user(), except that the object ID is left
+ * reserved/tombstoned.
+ */
+static inline void iommufd_object_tombstone_user(struct iommufd_ctx *ictx,
+						 struct iommufd_object *obj)
+{
+	int ret;
+
+	ret = iommufd_object_remove(ictx, obj, obj->id,
+				    REMOVE_WAIT_SHORTTERM | REMOVE_OBJ_TOMBSTONE);
+
+	/*
+	 * If there is a bug and we couldn't destroy the object then we did put
+	 * back the caller's users refcount and will eventually try to free it
+	 * again during close.
+	 */
+	WARN_ON(ret);
+}
+
 /*
  * The HWPT allocated by autodomains is used in possibly many devices and
  * is automatically destroyed when its refcount reaches zero.
diff --git a/drivers/iommu/iommufd/main.c b/drivers/iommu/iommufd/main.c
index 3df468f64e7d..5fd75aba068b 100644
--- a/drivers/iommu/iommufd/main.c
+++ b/drivers/iommu/iommufd/main.c
@@ -167,7 +167,7 @@ int iommufd_object_remove(struct iommufd_ctx *ictx,
 		goto err_xa;
 	}
 
-	xas_store(&xas, NULL);
+	xas_store(&xas, (flags & REMOVE_OBJ_TOMBSTONE) ? XA_ZERO_ENTRY : NULL);
 	if (ictx->vfio_ioas == container_of(obj, struct iommufd_ioas, obj))
 		ictx->vfio_ioas = NULL;
 	xa_unlock(&ictx->objects);
@@ -238,6 +238,7 @@ static int iommufd_fops_release(struct inode *inode, struct file *filp)
 	struct iommufd_ctx *ictx = filp->private_data;
 	struct iommufd_sw_msi_map *next;
 	struct iommufd_sw_msi_map *cur;
+	XA_STATE(xas, &ictx->objects, 0);
 	struct iommufd_object *obj;
 
 	/*
@@ -251,16 +252,30 @@ static int iommufd_fops_release(struct inode *inode, struct file *filp)
 	 */
 	while (!xa_empty(&ictx->objects)) {
 		unsigned int destroyed = 0;
-		unsigned long index;
 
-		xa_for_each(&ictx->objects, index, obj) {
-			if (!refcount_dec_if_one(&obj->users))
-				continue;
+		xas_set(&xas, 0);
+		for (;;) {
+			rcu_read_lock();
+			obj = xas_find(&xas, ULONG_MAX);
+			rcu_read_unlock();
+
+			if (!obj)
+				break;
+
+			if (!xa_is_zero(obj)) {
+				if (!refcount_dec_if_one(&obj->users))
+					continue;
+
+				iommufd_object_ops[obj->type].destroy(obj);
+				kfree(obj);
+			}
+
 			destroyed++;
-			xa_erase(&ictx->objects, index);
-			iommufd_object_ops[obj->type].destroy(obj);
-			kfree(obj);
+			xas_lock(&xas);
+			xas_store(&xas, NULL);
+			xas_unlock(&xas);
 		}
+
 		/* Bug related to users refcount */
 		if (WARN_ON(!destroyed))
 			break;
-- 
2.25.1


  reply	other threads:[~2025-06-23  9:57 UTC|newest]

Thread overview: 32+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-06-23  9:49 [PATCH v2 0/4] iommufd: Destroy vdevice on device unbind Xu Yilun
2025-06-23  9:49 ` Xu Yilun [this message]
2025-06-24 13:35   ` [PATCH v2 1/4] iommufd: Add iommufd_object_tombstone_user() helper Jason Gunthorpe
2025-06-25  7:24     ` Xu Yilun
2025-06-25  5:51   ` Aneesh Kumar K.V
2025-06-25  8:40     ` Xu Yilun
2025-06-23  9:49 ` [PATCH v2 2/4] iommufd/viommu: Fix the uninitialized iommufd_vdevice::ictx Xu Yilun
2025-06-24  3:24   ` Baolu Lu
2025-06-24  6:35     ` Xu Yilun
2025-06-23  9:49 ` [PATCH v2 3/4] iommufd: Destroy vdevice on idevice destroy Xu Yilun
2025-06-24  3:32   ` Baolu Lu
2025-06-24  8:11     ` Xu Yilun
2025-06-24  8:28       ` Tian, Kevin
2025-06-24  8:12     ` Tian, Kevin
2025-06-25  1:55       ` Baolu Lu
2025-06-24  6:47   ` Xu Yilun
2025-06-24  8:22   ` Tian, Kevin
2025-06-26  4:59     ` Xu Yilun
2025-06-24 14:53   ` Jason Gunthorpe
2025-06-24 23:57     ` Tian, Kevin
2025-06-25  1:36       ` Jason Gunthorpe
2025-06-25  2:11         ` Tian, Kevin
2025-06-25 12:33           ` Jason Gunthorpe
2025-06-25 10:06     ` Xu Yilun
2025-06-25 12:38       ` Jason Gunthorpe
2025-06-26  3:31         ` Xu Yilun
2025-06-26 14:36           ` Jason Gunthorpe
2025-06-25  6:40   ` Aneesh Kumar K.V
2025-06-25  9:38     ` Xu Yilun
2025-06-23  9:49 ` [PATCH v2 4/4] iommufd/selftest: Add coverage for vdevice tombstone Xu Yilun
2025-06-24 13:41   ` Jason Gunthorpe
2025-06-25  8:29     ` Xu Yilun

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=20250623094946.1714996-2-yilun.xu@linux.intel.com \
    --to=yilun.xu@linux.intel.com \
    --cc=aik@amd.com \
    --cc=aneesh.kumar@kernel.org \
    --cc=baolu.lu@linux.intel.com \
    --cc=dan.j.williams@intel.com \
    --cc=iommu@lists.linux.dev \
    --cc=jgg@nvidia.com \
    --cc=jgg@ziepe.ca \
    --cc=joro@8bytes.org \
    --cc=kevin.tian@intel.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=nicolinc@nvidia.com \
    --cc=robin.murphy@arm.com \
    --cc=shuah@kernel.org \
    --cc=will@kernel.org \
    --cc=yilun.xu@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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®