From nobody Thu Dec 18 07:20:25 2025 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1D59AC61D85 for ; Tue, 21 Nov 2023 18:05:11 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234712AbjKUSFK (ORCPT ); Tue, 21 Nov 2023 13:05:10 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:38424 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234554AbjKUSEo (ORCPT ); Tue, 21 Nov 2023 13:04:44 -0500 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id B94EF1710 for ; Tue, 21 Nov 2023 10:04:18 -0800 (PST) Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 25AD316F2; Tue, 21 Nov 2023 10:05:05 -0800 (PST) Received: from e121345-lin.cambridge.arm.com (e121345-lin.cambridge.arm.com [10.1.196.40]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id 595913F6C4; Tue, 21 Nov 2023 10:04:17 -0800 (PST) From: Robin Murphy To: joro@8bytes.org, will@kernel.org Cc: iommu@lists.linux.dev, jgg@nvidia.com, baolu.lu@linux.intel.com, linux-kernel@vger.kernel.org, jsnitsel@redhat.com Subject: [PATCH v6 3/7] iommu: Validate that devices match domains Date: Tue, 21 Nov 2023 18:03:59 +0000 Message-Id: <097c6f30480e4efe12195d00ba0e84ea4837fb4c.1700589539.git.robin.murphy@arm.com> X-Mailer: git-send-email 2.39.2.101.g768bb238c484.dirty In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Before we can allow drivers to coexist, we need to make sure that one driver's domain ops can't misinterpret another driver's dev_iommu_priv data. To that end, add a token to the domain so we can remember how it was allocated - for now this may as well be the device ops, since they still correlate 1:1 with drivers. We can trust ourselves for internal default domain attachment, so add checks to cover all the public attach interfaces. Reviewed-by: Lu Baolu Reviewed-by: Jason Gunthorpe Reviewed-by: Jerry Snitselaar Signed-off-by: Robin Murphy --- v4: Cover iommu_attach_device_pasid() as well, and improve robustness against theoretical attempts to attach a noiommu group. v6: Cover new iommu_domain_alloc_user() sites as well. I don't entirely dislike the idea of tying this into the domain ops, but I'd rather do the simple thing for now and revisit that in future, since domain ops also deserve some other cleanup. --- drivers/iommu/iommu.c | 10 ++++++++++ drivers/iommu/iommufd/hw_pagetable.c | 2 ++ include/linux/iommu.h | 2 +- 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index 7fafd073c33e..8e4436c606d3 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -2117,6 +2117,7 @@ static struct iommu_domain *__iommu_domain_alloc(cons= t struct iommu_ops *ops, return NULL; =20 domain->type =3D type; + domain->owner =3D ops; /* * If not already set, assume all sizes by default; the driver * may override this later @@ -2282,10 +2283,16 @@ struct iommu_domain *iommu_get_dma_domain(struct de= vice *dev) static int __iommu_attach_group(struct iommu_domain *domain, struct iommu_group *group) { + struct device *dev; + if (group->domain && group->domain !=3D group->default_domain && group->domain !=3D group->blocking_domain) return -EBUSY; =20 + dev =3D iommu_group_first_dev(group); + if (!dev_has_iommu(dev) || dev_iommu_ops(dev) !=3D domain->owner) + return -EINVAL; + return __iommu_group_set_domain(group, domain); } =20 @@ -3477,6 +3484,9 @@ int iommu_attach_device_pasid(struct iommu_domain *do= main, if (!group) return -ENODEV; =20 + if (!dev_has_iommu(dev) || dev_iommu_ops(dev) !=3D domain->owner) + return -EINVAL; + mutex_lock(&group->mutex); curr =3D xa_cmpxchg(&group->pasid_array, pasid, NULL, domain, GFP_KERNEL); if (curr) { diff --git a/drivers/iommu/iommufd/hw_pagetable.c b/drivers/iommu/iommufd/h= w_pagetable.c index 2abbeafdbd22..5be7f513b622 100644 --- a/drivers/iommu/iommufd/hw_pagetable.c +++ b/drivers/iommu/iommufd/hw_pagetable.c @@ -135,6 +135,7 @@ iommufd_hwpt_paging_alloc(struct iommufd_ctx *ictx, str= uct iommufd_ioas *ioas, hwpt->domain =3D NULL; goto out_abort; } + hwpt->domain->owner =3D ops; } else { hwpt->domain =3D iommu_domain_alloc(idev->dev->bus); if (!hwpt->domain) { @@ -233,6 +234,7 @@ iommufd_hwpt_nested_alloc(struct iommufd_ctx *ictx, hwpt->domain =3D NULL; goto out_abort; } + hwpt->domain->owner =3D ops; =20 if (WARN_ON_ONCE(hwpt->domain->type !=3D IOMMU_DOMAIN_NESTED)) { rc =3D -EINVAL; diff --git a/include/linux/iommu.h b/include/linux/iommu.h index 7d87423663d4..51b18a4b5834 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h @@ -106,7 +106,7 @@ struct iommu_domain { unsigned type; const struct iommu_domain_ops *ops; const struct iommu_dirty_ops *dirty_ops; - + const struct iommu_ops *owner; /* Whose domain_alloc we came from */ unsigned long pgsize_bitmap; /* Bitmap of page sizes in use */ struct iommu_domain_geometry geometry; struct iommu_dma_cookie *iova_cookie; --=20 2.39.2.101.g768bb238c484.dirty