From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id BBEE5386C3B; Tue, 25 Aug 2026 13:38:25 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787665107; cv=none; b=o2tF0URhzbgkHGmjr7+QOJ5pcHVBuXqH6krwN93uJadyacAhMsDkK7ZS8F3AZZI2rdvB1VNCwFO376mqyQ7vSQrIwdnGDK+82jbSpuzmgONzTkrtOGTyy1XfTjqH44NhY270qmy3dgzua390vTVFmNJ+FwkiCSR+JfPswWGL9yQ= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787665107; c=relaxed/simple; bh=7cu9rZkZKdnQjt22n82/N6Y9zdyX4CNPtBz39Wjd38o=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=fUyglec4AqY7ydREnvkYBK5oVfIViLn5TbODxns2i2iQ/peMGqmP7poGIJBm7ZNGepnGCL0JU++/bc4FHORqpMKzDWBS6Kgt8iZHD/qg9TBg095PXoPfraFufNj7LSwAOgEPSN9FHj3J8k6U7C9moRrw4o6pyZhxr0ZgaXg8mzI= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linuxfoundation.org header.i=@linuxfoundation.org header.b=lDC1ZF8M; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linuxfoundation.org header.i=@linuxfoundation.org header.b="lDC1ZF8M" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 1EA761F000E9; Tue, 25 Aug 2026 13:38:24 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linuxfoundation.org; s=korg; t=1787665105; bh=hjUVhm1apbKDpgCoJwxgkkfTMaqdw09ZFkBQ58mTTB0=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=lDC1ZF8MkzXwRJ40f4tOC/flF2XaLYzy0+vAX+S4zhPj2+IC/5tBL0WMY2bpYTPlA Vol/cc03pg+IZzWsiF9mkjdBqFwpf8m3Ks3PCZnn8iK6JMsHvKGfYO23/Wfy6Mq2Zr VP2DD+JV5Fo/6XzY5abJoezcoHI/QkCYAhIK4IFU= From: Greg Kroah-Hartman To: stable@vger.kernel.org Cc: Greg Kroah-Hartman , patches@lists.linux.dev, Nicolin Chen , Shameer Kolothum , Jason Gunthorpe , Will Deacon Subject: [PATCH 6.18 10/94] iommu/tegra241-cmdqv: Fix CMD_SYNC use-after-free on teardown Date: Tue, 25 Aug 2026 15:25:06 +0200 Message-ID: <20260825132542.284177065@linuxfoundation.org> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260825132541.887883084@linuxfoundation.org> References: <20260825132541.887883084@linuxfoundation.org> User-Agent: quilt/0.69 X-stable: review X-Patchwork-Hint: ignore Precedence: bulk X-Mailing-List: patches@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit 6.18-stable review patch. If anyone has any objections, please let me know. ------------------ From: Shameer Kolothum commit 9ff145a25c5c8a26b06ef7cf558fb536b18bba6d upstream. arm_smmu_impl_remove() is registered as a devres action in arm_smmu_impl_probe(), before arm_smmu_init_queues() allocates smmu->cmdq.q.base. On a devres unwind, whether a failed probe or an unbind, the queue is freed first and arm_smmu_impl_remove() then runs tegra241_cmdqv_remove_vintf(), whose VINTF deinit issues a CMD_SYNC on the freed memory. Observed during testing with a QEMU hack that makes the VCMDQ fail to enable, so the impl reset fails and probe aborts into the devres unwind: platform NVDA200C:00: tegra241_cmdqv: VINTF0: VCMDQ0/LVCMDQ0: failed to enable, STATUS=0x00000000 platform NVDA200C:00: tegra241_cmdqv: VINTF0: VCMDQ0/LVCMDQ0: GERRORN=0x0, GERROR=0x4, CONS=0x0 platform NVDA200C:00: tegra241_cmdqv: VINTF0: VCMDQ0/LVCMDQ0: uncleared error detected, resetting arm-smmu-v3 arm-smmu-v3.0.auto: failed to reset impl arm-smmu-v3 arm-smmu-v3.0.auto: probe with driver arm-smmu-v3 failed with error -110 Unable to handle kernel paging request at virtual address ffff8000891e0098 ... Internal error: Oops: 0000000096000047 [#1] SMP ... Call trace: arm_smmu_cmdq_issue_cmdlist+0x320/0x6fc (P) tegra241_vcmdq_hw_deinit+0x98/0x168 tegra241_vintf_hw_deinit+0x5c/0x1b0 tegra241_cmdqv_remove_vintf+0x34/0xec tegra241_cmdqv_remove+0x40/0x9c arm_smmu_impl_remove+0x20/0x30 devm_action_release+0x14/0x20 devres_release_all+0xa8/0x110 device_unbind_cleanup+0x18/0x84 really_probe+0x1f0/0x29c Drop the VINTF deinit from tegra241_cmdqv_remove_vintf() so the unwind no longer touches the freed queue. Quiesce the VINTFs earlier instead. Add a device_disable() impl op and run it from arm_smmu_disable_action() while the CMDQ is still up. That handles a live unbind. A failed reset is already handled because tegra241_vintf_hw_init() deinits the VINTF on its own error path. tegra241_cmdqv_remove_vintf() is also used by the iommufd viommu destroy path, so quiesce there too. Fixes: 4dc0d12474f9 ("iommu/tegra241-cmdqv: Add user-space use support") Cc: stable@vger.kernel.org Reviewed-by: Nicolin Chen Signed-off-by: Shameer Kolothum Reviewed-by: Jason Gunthorpe Signed-off-by: Will Deacon Signed-off-by: Greg Kroah-Hartman --- drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 2 ++ drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h | 1 + drivers/iommu/arm/arm-smmu-v3/tegra241-cmdqv.c | 15 +++++++++++++-- 3 files changed, 16 insertions(+), 2 deletions(-) --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c @@ -4929,6 +4929,8 @@ static void arm_smmu_device_shutdown(str { struct arm_smmu_device *smmu = platform_get_drvdata(pdev); + if (smmu->impl_ops && smmu->impl_ops->device_disable) + smmu->impl_ops->device_disable(smmu); arm_smmu_device_disable(smmu); } --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h @@ -718,6 +718,7 @@ struct arm_smmu_strtab_cfg { struct arm_smmu_impl_ops { int (*device_reset)(struct arm_smmu_device *smmu); + void (*device_disable)(struct arm_smmu_device *smmu); void (*device_remove)(struct arm_smmu_device *smmu); int (*init_structures)(struct arm_smmu_device *smmu); struct arm_smmu_cmdq *(*get_secondary_cmdq)( --- a/drivers/iommu/arm/arm-smmu-v3/tegra241-cmdqv.c +++ b/drivers/iommu/arm/arm-smmu-v3/tegra241-cmdqv.c @@ -763,8 +763,6 @@ static void tegra241_cmdqv_remove_vintf( struct tegra241_vintf *vintf = cmdqv->vintfs[idx]; u16 lidx; - tegra241_vintf_hw_deinit(vintf); - /* Remove LVCMDQ resources */ for (lidx = 0; lidx < vintf->cmdqv->num_lvcmdqs_per_vintf; lidx++) if (vintf->lvcmdqs[lidx]) @@ -781,6 +779,17 @@ static void tegra241_cmdqv_remove_vintf( } } +static void tegra241_cmdqv_hw_disable(struct arm_smmu_device *smmu) +{ + struct tegra241_cmdqv *cmdqv = + container_of(smmu, struct tegra241_cmdqv, smmu); + u16 idx; + + for (idx = 0; idx < cmdqv->num_vintfs; idx++) + if (cmdqv->vintfs[idx]) + tegra241_vintf_hw_deinit(cmdqv->vintfs[idx]); +} + static void tegra241_cmdqv_remove(struct arm_smmu_device *smmu) { struct tegra241_cmdqv *cmdqv = @@ -846,6 +855,7 @@ static struct arm_smmu_impl_ops tegra241 /* For in-kernel use */ .get_secondary_cmdq = tegra241_cmdqv_get_cmdq, .device_reset = tegra241_cmdqv_hw_reset, + .device_disable = tegra241_cmdqv_hw_disable, .device_remove = tegra241_cmdqv_remove, /* For user-space use */ .hw_info = tegra241_cmdqv_hw_info, @@ -1212,6 +1222,7 @@ static void tegra241_cmdqv_destroy_vintf if (vintf->mmap_offset) iommufd_viommu_destroy_mmap(&vintf->vsmmu.core, vintf->mmap_offset); + tegra241_vintf_hw_deinit(vintf); tegra241_cmdqv_remove_vintf(vintf->cmdqv, vintf->idx); }