mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Nicolin Chen <nicolinc@nvidia.com>
To: Yi Liu <yi.l.liu@intel.com>
Cc: Baolu Lu <baolu.lu@linux.intel.com>, <joro@8bytes.org>,
	Jason Gunthorpe <jgg@nvidia.com>, Will Deacon <will@kernel.org>,
	Robin Murphy <robin.murphy@arm.com>,
	Kevin Tian <kevin.tian@intel.com>,
	"Jean-Philippe Brucker" <jpb@kernel.org>, <iommu@lists.linux.dev>,
	<linux-kernel@vger.kernel.org>
Subject: Re: [PATCH v1 3/4] iommu: Unpublish the old attach handle before the group replace callback
Date: Sun, 1 Nov 2026 21:54:32 -0800	[thread overview]
Message-ID: <auglmP/oFZNhnja/@nvidia.com> (raw)
In-Reply-To: <5512edd1-3c52-4e8a-a38f-3a5f1457cdaf@intel.com>

On Mon, Nov 02, 2026 at 11:30:02AM +0800, Yi Liu wrote:
> On 11/1/26 13:53, Baolu Lu wrote:
> > This doesn't fix the same-domain replace issue, which can still result
> > in a use-after-free bug. I agree that this needs a separate lifetime
> > mechanism as stated in the cover letter. But is it possible to prevent
> > the same-domain replace case from going through this interface?
> 
> fwiw, iommufd already guards this at the device-replace layer
> (iommufd_device_do_replace() short-circuits when hwpt == old_hwpt) [1],
> so IOMMUFD callers can't currently trigger this. But that's a caller-side
> convention, not something
> iommu_replace_group_handle()/iommu_replace_device_pasid() enforce themselves
> - so it's still
> reachable if a future/other caller doesn't do the same check. Worth
> deciding whether to push the guard down into the core API, or document
> it as a caller contract.

I can add a fifth patch. Please see if it looks good to you.

Subject: [PATCH] iommu: Reject a same-domain replace in the attach handle APIs

Both iommu_replace_group_handle() and iommu_replace_device_pasid() skip the
driver callback when the new domain is the one currently attached. In that
case, nothing flushes the pending faults that may still be holding the old
handle. Then, the caller frees the old handle once the replace returns, so
such a fault would hit a use-after-free.

No caller does this today, since iommufd_device_do_replace() returns early
when the new hwpt is the old one. However, it is only a caller convention,
which neither API enforces.

Reject a same-domain replace in both APIs with a WARN_ON, and document it
in their kernel-docs.

Suggested-by: Lu Baolu <baolu.lu@linux.intel.com>
Signed-off-by: Nicolin Chen <nicolinc@nvidia.com>
---
 drivers/iommu/iommu.c | 34 +++++++++++++++++++++++++++-------
 1 file changed, 27 insertions(+), 7 deletions(-)

diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index 3fea48d3538ad..a9bc4ca5dbb4e 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -3716,6 +3716,10 @@ EXPORT_SYMBOL_GPL(iommu_attach_device_pasid);
  * Caller should always provide a new handle to avoid race with the paths
  * that have lockless reference to handle if it intends to pass a valid handle.
  *
+ * The @domain must not be the domain currently attached to the @pasid. Such a
+ * same-domain replace would skip the driver callback flushing pending faults.
+ * Then, those faults could use the old handle after the caller frees it.
+ *
  * Return 0 on success, or an error.
  */
 int iommu_replace_device_pasid(struct iommu_domain *domain,
@@ -3785,15 +3789,17 @@ int iommu_replace_device_pasid(struct iommu_domain *domain,
 	}
 
 	curr_domain = pasid_array_entry_to_domain(curr);
-	ret = 0;
-
-	if (curr_domain != domain) {
-		ret = __iommu_set_group_pasid(domain, group,
-					      pasid, curr_domain);
-		if (ret)
-			entry = curr; /* restore the old handle */
+	/* Same as iommu_replace_group_handle(), reject a same-domain replace */
+	if (WARN_ON(curr_domain == domain)) {
+		entry = curr; /* restore the old handle */
+		ret = -EINVAL;
+		goto out_store;
 	}
 
+	ret = __iommu_set_group_pasid(domain, group, pasid, curr_domain);
+	if (ret)
+		entry = curr; /* restore the old handle */
+
 out_store:
 	/*
 	 * The xa_store() above reserved the memory, and the group->mutex
@@ -3985,6 +3991,10 @@ EXPORT_SYMBOL_NS_GPL(iommu_detach_group_handle, "IOMMUFD_INTERNAL");
  *
  * Caller should always provide a new handle to avoid race with the paths
  * that have lockless reference to handle.
+ *
+ * The @new_domain must not be the domain currently attached to the group. Such
+ * a same-domain replace would skip the driver callback flushing pending faults.
+ * Then, those faults could use the old handle after the caller frees it.
  */
 int iommu_replace_group_handle(struct iommu_group *group,
 			       struct iommu_domain *new_domain,
@@ -3997,6 +4007,16 @@ int iommu_replace_group_handle(struct iommu_group *group,
 		return -EINVAL;
 
 	mutex_lock(&group->mutex);
+	/*
+	 * A same-domain replace would skip the driver callback flushing pending
+	 * faults. Then, those faults could use the old handle after the caller
+	 * frees it.
+	 */
+	if (WARN_ON(group->domain == new_domain)) {
+		ret = -EINVAL;
+		goto err_unlock;
+	}
+
 	entry = iommu_make_pasid_array_entry(new_domain, handle);
 	/*
 	 * iommu_attach_handle_get() runs without the group mutex, so unpublish
-- 

Thanks
Nicolin

  reply	other threads:[~2026-11-02  5:54 UTC|newest]

Thread overview: 23+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-29 21:51 [PATCH v1 0/4] iommu: Fix attach handle publication ordering Nicolin Chen
2026-09-29 21:51 ` [PATCH v1 1/4] iommu: Unpublish the attach handle before the group detach callback Nicolin Chen
2026-10-29  7:18   ` Tian, Kevin
2026-11-01  2:01   ` Baolu Lu
2026-09-29 21:51 ` [PATCH v1 2/4] iommu: Unpublish the attach handle before the PASID " Nicolin Chen
2026-10-29  7:18   ` Tian, Kevin
2026-11-01  2:13   ` Baolu Lu
2026-09-29 21:51 ` [PATCH v1 3/4] iommu: Unpublish the old attach handle before the group replace callback Nicolin Chen
2026-10-29  7:25   ` Tian, Kevin
2026-10-29 11:00     ` Yi Liu
2026-10-29 18:45       ` Jason Gunthorpe
2026-10-30  8:03         ` Tian, Kevin
2026-10-30  8:22         ` Yi Liu
2026-10-30 15:21           ` Jason Gunthorpe
2026-11-01  5:53   ` Baolu Lu
2026-11-02  3:30     ` Yi Liu
2026-11-02  5:54       ` Nicolin Chen [this message]
2026-11-02  6:05         ` Baolu Lu
2026-09-29 21:51 ` [PATCH v1 4/4] iommu: Unpublish the old attach handle before the PASID " Nicolin Chen
2026-10-29  7:26   ` Tian, Kevin
2026-11-01  5:54   ` Baolu Lu
2026-10-28 18:58 ` [PATCH v1 0/4] iommu: Fix attach handle publication ordering Nicolin Chen
2026-10-29 11:00 ` Yi Liu

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=auglmP/oFZNhnja/@nvidia.com \
    --to=nicolinc@nvidia.com \
    --cc=baolu.lu@linux.intel.com \
    --cc=iommu@lists.linux.dev \
    --cc=jgg@nvidia.com \
    --cc=joro@8bytes.org \
    --cc=jpb@kernel.org \
    --cc=kevin.tian@intel.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=robin.murphy@arm.com \
    --cc=will@kernel.org \
    --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 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®