From: Nicolin Chen <nicolinc@nvidia.com>
To: <joro@8bytes.org>, Lu Baolu <baolu.lu@linux.intel.com>,
Kevin Tian <kevin.tian@intel.com>, Yi Liu <yi.l.liu@intel.com>
Cc: Will Deacon <will@kernel.org>,
Robin Murphy <robin.murphy@arm.com>,
Jean-Philippe Brucker <jpb@kernel.org>,
Jason Gunthorpe <jgg@nvidia.com>, <iommu@lists.linux.dev>,
<linux-kernel@vger.kernel.org>
Subject: [PATCH v2 4/5] iommu: Unpublish the old attach handle before the PASID replace callback
Date: Sun, 1 Nov 2026 23:04:38 -0800 [thread overview]
Message-ID: <33748eda55ccd91c32729d5d212b389742a6b1ec.1793602084.git.nicolinc@nvidia.com> (raw)
In-Reply-To: <cover.1793602084.git.nicolinc@nvidia.com>
Similar to iommu_replace_group_handle(), iommu_replace_device_pasid() has
the same inert reserve as the group path and the UAF window:
core, holding group->mutex fault path, no group->mutex
========================== ===========================
xa_cmpxchg() ,-- old handle stays published
no-op, the slot is occupied |
__iommu_set_group_pasid() |
driver attach/detach ops |
iopf_queue_flush_dev() |
| iommu_attach_handle_get()
| reads old_handle
xa_store(new entry) `-- window closes
mutex_unlock()
kfree(old_handle) [caller]
UAF: old_handle->domain->iopf_handler()
Store XA_ZERO_ENTRY outright, just as the group path now does.
Fixes: 8a9e1e773f60 ("iommu: Introduce a replace API for device pasid")
Cc: stable@vger.kernel.org
Reviewed-by: Kevin Tian <kevin.tian@intel.com>
Reviewed-by: Yi Liu <yi.l.liu@intel.com>
Reviewed-by: Lu Baolu <baolu.lu@linux.intel.com>
Signed-off-by: Nicolin Chen <nicolinc@nvidia.com>
---
drivers/iommu/iommu.c | 19 ++++++++++++-------
1 file changed, 12 insertions(+), 7 deletions(-)
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index 0a199c1c3141e..3fea48d3538ad 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -3751,8 +3751,13 @@ int iommu_replace_device_pasid(struct iommu_domain *domain,
}
entry = iommu_make_pasid_array_entry(domain, handle);
- curr = xa_cmpxchg(&group->pasid_array, pasid, NULL,
- XA_ZERO_ENTRY, GFP_KERNEL);
+ /*
+ * iommu_attach_handle_get() runs without the group mutex, so unpublish
+ * the old handle before the driver callback: a fault must not resolve
+ * to either domain while the switch is in progress. This reserves the
+ * slot too, so the store below cannot fail.
+ */
+ curr = xa_store(&group->pasid_array, pasid, XA_ZERO_ENTRY, GFP_KERNEL);
if (xa_is_err(curr)) {
ret = xa_err(curr);
goto out_unlock;
@@ -3776,7 +3781,7 @@ int iommu_replace_device_pasid(struct iommu_domain *domain,
if (curr == entry) {
WARN_ON(1);
ret = -EINVAL;
- goto out_unlock;
+ goto out_store;
}
curr_domain = pasid_array_entry_to_domain(curr);
@@ -3786,16 +3791,16 @@ int iommu_replace_device_pasid(struct iommu_domain *domain,
ret = __iommu_set_group_pasid(domain, group,
pasid, curr_domain);
if (ret)
- goto out_unlock;
+ entry = curr; /* restore the old handle */
}
+out_store:
/*
- * The above xa_cmpxchg() reserved the memory, and the
- * group->mutex is held, this cannot fail.
+ * The xa_store() above reserved the memory, and the group->mutex
+ * is held, this cannot fail.
*/
WARN_ON(xa_is_err(xa_store(&group->pasid_array,
pasid, entry, GFP_KERNEL)));
-
out_unlock:
mutex_unlock(&group->mutex);
return ret;
--
2.43.0
next prev parent reply other threads:[~2026-11-02 7:05 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-02 7:04 [PATCH v2 0/5] iommu: Fix attach handle publication ordering Nicolin Chen
2026-11-02 7:04 ` [PATCH v2 1/5] iommu: Unpublish the attach handle before the group detach callback Nicolin Chen
2026-11-02 7:04 ` [PATCH v2 2/5] iommu: Unpublish the attach handle before the PASID " Nicolin Chen
2026-11-02 7:04 ` [PATCH v2 3/5] iommu: Unpublish the old attach handle before the group replace callback Nicolin Chen
2026-11-02 7:04 ` Nicolin Chen [this message]
2026-11-02 7:04 ` [PATCH v2 5/5] iommu: Reject a same-domain replace in the attach handle APIs Nicolin Chen
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=33748eda55ccd91c32729d5d212b389742a6b1ec.1793602084.git.nicolinc@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®