Linux KVM/arm64 development list
 help / color / mirror / Atom feed
From: Mostafa Saleh <smostafa@google.com>
To: sashiko-reviews@lists.linux.dev
Cc: kvmarm@lists.linux.dev, Oliver Upton <oupton@kernel.org>,
	Marc Zyngier <maz@kernel.org>
Subject: Re: [PATCH v9 11/25] iommu/arm-smmu-v3-kvm: Add the kernel driver
Date: Thu, 15 Oct 2026 20:52:47 +0000	[thread overview]
Message-ID: <atE9H7wWlnlqYqV3@google.com> (raw)
In-Reply-To: <sashiko-outbox-173402@kernel.org>

On Thu, Oct 15, 2026 at 08:35:03PM +0000, sashiko-bot@kernel.org wrote:
> Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
> - [Critical] iommu/arm-smmu-v3: native driver fallback bypasses pKVM DMA isolation
> - [High] mm: UAF of smmu due to devres LIFO inversion on deferred probe
> - [Medium] iommu/arm-smmu-v3: aux device creation failure aborts initialization for remaining SMMUs
> --
> 
> commit 989c8869198ba4ebe30e4fc7554bb66910985d0b
> Author: Mostafa Saleh <smostafa@google.com>
> 
> iommu/arm-smmu-v3-kvm: Add the kernel driver
>     
> When KVM runs in protected mode with CONFIG_ARM_SMMU_V3_PKVM, the
> hypervisor owns the SMMUv3 hardware and presents emulated SMMUs to the
> host through trap and emulate. This patch adds the host side of the driver,
> using an auxiliary device approach for the emulated SMMUs.
> 
> > diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-pkvm-init.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-pkvm-init.c
> > new file mode 100644
> > index 0000000000000..5c5f0ff455e3b
> > --- /dev/null
> > +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-pkvm-init.c
> 
> [ ... ]
> 
> > +static int __init kvm_arm_smmu_v3_register(void)
> > +{
> > +	size_t nr_pages = smmu_hyp_pgt_pages();
> > +	int ret;
> > +
> > +	if (!is_protected_kvm_enabled() || !nr_pages)
> > +		return 0;
> > +
> > +	ret = kvm_arm_smmu_array_alloc();
> > +	if (ret)
> > +		goto out_err;
> > +
> > +	ret = platform_driver_probe(&smmuv3_nesting_driver, smmuv3_nesting_probe);
> > +	if (ret)
> > +		goto out_free;
> > +
> > +	ret = pkvm_iommu_register_driver(&kvm_nvhe_sym(smmu_ops), nr_pages);
> > +	if (ret)
> > +		goto out_unregister;
> > +
> > +	/*
> > +	 * These variables are stored in the nVHE image, and won't be accessible
> > +	 * after KVM initialization. Ownership of kvm_arm_smmu_array will be
> > +	 * transferred to the hypervisor as well.
> > +	 */
> > +	kvm_hyp_arm_smmu_v3_smmus = kvm_arm_smmu_array;
> > +	kvm_hyp_arm_smmu_v3_count = kvm_arm_smmu_cur;
> > +	return ret;
> > +
> > +out_unregister:
> > +	platform_driver_unregister(&smmuv3_nesting_driver);
> 
> [Severity: Critical]
> Does this fail-open behavior bypass pKVM DMA isolation?
> 
> If an SMMU is rejected by smmuv3_nesting_probe() (e.g. due to Cavium errata
> or unaligned MMIO), or if pkvm_iommu_register_driver() fails, the affected
> SMMU devices are left unbound or the nesting driver is unregistered.
> 
> Later, the native arm_smmu_driver is registered unconditionally in
> arm-smmu-v3.c and will successfully bind to these unbound SMMU devices.
> Since the hypervisor wasn't given the MMIO regions for the skipped SMMUs,
> it does not enforce stage-2 trapping on them. The host EL1 could then
> program these native SMMUs to perform unrestricted DMA into pKVM-protected
> guest or hypervisor memory, compromising protected VMs.
> 

Also by design as replied in v8:
https://lore.kernel.org/all/arKa-8QbSSQFrUbJ@google.com/

> > +out_free:
> > +	kvm_arm_smmu_array_free();
> > +out_err:
> > +	kvm_arm_smmu_count = 0;
> > +	kvm_arm_smmu_array = NULL;
> > +	return ret;
> > +}
> > +
> > +static int __init smmu_create_aux_device(struct device *dev, void *data)
> > +{
> > +	static int dev_id;
> > +	struct auxiliary_device *auxdev;
> > +
> > +	auxdev = __devm_auxiliary_device_create(dev, "protected_kvm",
> > +						"smmu_v3_emu", NULL, dev_id++);
> > +	if (!auxdev)
> > +		return -ENODEV;
> > +	return 0;
> > +}
> > +
> > +static int __init kvm_arm_smmu_v3_post_init(void)
> > +{
> > +	if (!kvm_arm_smmu_count)
> > +		return 0;
> > +
> > +	/*
> > +	 * If KVM failed to initialise, the host stage-2 is never enabled and
> > +	 * the SMMUs are driven natively through the same path.
> > +	 */
> > +	WARN_ON(driver_for_each_device(&smmuv3_nesting_driver.driver, NULL,
> > +				       NULL, smmu_create_aux_device));
> 
> [Severity: Medium]
> Does this halt initialization for all remaining SMMUs if one fails?
> 
> In kvm_arm_smmu_v3_post_init(), driver_for_each_device() iterates over all
> bound SMMUs. If smmu_create_aux_device() fails (e.g. due to an ID collision
> or memory allocation failure in __devm_auxiliary_device_create()), it
> returns -ENODEV.
> 
> The core driver_for_each_device() function halts iteration and returns
> immediately upon receiving a non-zero value. Consequently, if a single SMMU
> fails aux device creation, all subsequent SMMUs are silently skipped. These
> skipped SMMUs won't be probed by the host's arm_smmu_driver_emu, breaking
> DMA translation for any peripherals behind them.
> 
> Should the callback log the error and return 0 to allow the remaining
> devices to initialize?
> 

If anyone fails the system is not trusted so there is no point of
creating the others.

> > diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
> > index c2ec33c763a0f..66f38c54742b8 100644
> > --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
> > +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
> 
> [ ... ]
> 
> > +static int arm_smmu_device_probe_emu(struct auxiliary_device *auxdev,
> > +				     const struct auxiliary_device_id *id)
> > +{
> > +	struct device *parent = auxdev->dev.parent;
> > +	void *group;
> > +	int ret;
> > +
> > +	dev_info(&auxdev->dev, "Probing from %s\n", dev_name(parent));
> > +	group = devres_open_group(parent, NULL, GFP_KERNEL);
> > +	if (!group)
> > +		return -ENOMEM;
> > +
> > +	ret = arm_smmu_device_probe(to_platform_device(parent));
> > +	if (ret)
> > +		devres_release_group(parent, group);
> > +	else
> > +		devres_close_group(parent, group);
> > +	return ret;
> > +}
> > +
> > +static void arm_smmu_device_remove_emu(struct auxiliary_device *auxdev)
> > +{
> > +	arm_smmu_device_remove(to_platform_device(auxdev->dev.parent));
> > +}
> 
> [Severity: High]
> Can this lead to a use-after-free of the smmu struct due to devres LIFO
> inversion during a deferred probe retry?
> 
> If arm_smmu_device_probe() returns -EPROBE_DEFER (e.g. from
> iommu_device_register() -> bus_iommu_probe() -> probe_iommu_group()),
> arm_smmu_device_probe_emu() correctly cleans up and returns the error,
> causing the auxiliary bus to defer the probe.
> 
> However, __devm_auxiliary_device_create() has already proceeded to register
> the auxiliary_device_destroy action on the parent's devres list. Later,
> when the deferred probe retries and succeeds, arm_smmu_device_probe()
> allocates the smmu struct via devm_kzalloc() and attaches it to the parent's
> devres list *after* the destroy action.
> 
> On parent platform device removal (e.g. via device tree overlay removal or
> system teardown), devres_release_all(parent) destroys devres actions in LIFO
> order. It first frees the smmu struct, and subsequently executes
> auxiliary_device_destroy. This unregisters the aux device and triggers
> arm_smmu_device_remove_emu(), which then dereferences the freed smmu pointer.

My assumption is that the platform device can't be removed as the
comment above, the overlay support has no in-kernel user nor a uAPI.

Not sure what does "system teardown" mean, but shutdown won't call
devres_release_all(). So I believe there is not path to remove the
platform device in that case.

However, as hardening, I might just call auxiliary_device_create()
instead of __devm_auxiliary_device_create().

Thanks,
Mostafa

> 
> -- 
> Sashiko AI review · https://sashiko.dev/#/patchset/20261015200903.2735565-1-smostafa@google.com?part=11

  reply	other threads:[~2026-10-15 20:52 UTC|newest]

Thread overview: 55+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-15 20:08 [PATCH v9 00/25] KVM: arm64: SMMUv3 driver for pKVM (trap and emulate) Mostafa Saleh
2026-10-15 20:08 ` [PATCH v9 01/25] KVM: arm64: Donate MMIO to the hypervisor Mostafa Saleh
2026-10-15 20:08 ` [PATCH v9 02/25] iommu/arm-smmu-v3: Move Queue and STE functions to header Mostafa Saleh
2026-10-15 20:08 ` [PATCH v9 03/25] iommu/arm-smmu-v3: Move IDR parsing to common functions Mostafa Saleh
2026-10-20 19:02   ` Nicolin Chen
2026-10-15 20:08 ` [PATCH v9 04/25] iommu/arm-smmu-v3: Move hitless machinery to common code Mostafa Saleh
2026-10-15 20:08 ` [PATCH v9 05/25] iommu/arm-smmu-v3: Move RangeInval " Mostafa Saleh
2026-10-20 19:11   ` Nicolin Chen
2026-10-15 20:08 ` [PATCH v9 06/25] KVM: arm64: iommu: Introduce IOMMU driver infrastructure Mostafa Saleh
2026-10-15 20:08 ` [PATCH v9 07/25] KVM: arm64: iommu: Shadow host stage-2 page table Mostafa Saleh
2026-10-15 20:08 ` [PATCH v9 08/25] KVM: arm64: iommu: Add memory pool Mostafa Saleh
2026-10-15 20:18   ` sashiko-bot
2026-10-15 20:40     ` Mostafa Saleh
2026-10-15 20:08 ` [PATCH v9 09/25] KVM: arm64: iommu: Support DABT for IOMMU Mostafa Saleh
2026-10-15 20:08 ` [PATCH v9 10/25] iommu/arm-smmu-v3-kvm: Add SMMUv3 driver Mostafa Saleh
2026-10-29 21:18   ` Nicolin Chen
2026-10-15 20:08 ` [PATCH v9 11/25] iommu/arm-smmu-v3-kvm: Add the kernel driver Mostafa Saleh
2026-10-15 20:35   ` sashiko-bot
2026-10-15 20:52     ` Mostafa Saleh [this message]
2026-10-15 20:08 ` [PATCH v9 12/25] iommu/arm-smmu-v3-kvm: Probe SMMU HW Mostafa Saleh
2026-10-15 20:08 ` [PATCH v9 13/25] iommu/arm-smmu-v3-kvm: Add MMIO emulation Mostafa Saleh
2026-10-15 20:30   ` sashiko-bot
2026-10-15 21:00     ` Mostafa Saleh
2026-10-15 20:08 ` [PATCH v9 14/25] iommu/arm-smmu-v3-kvm: Shadow the command queue Mostafa Saleh
2026-10-15 20:28   ` sashiko-bot
2026-10-15 21:01     ` Mostafa Saleh
2026-10-15 20:08 ` [PATCH v9 15/25] iommu/arm-smmu-v3-kvm: Add CMDQ functions Mostafa Saleh
2026-10-15 20:30   ` sashiko-bot
2026-10-15 21:11     ` Mostafa Saleh
2026-10-15 20:08 ` [PATCH v9 16/25] iommu/arm-smmu-v3-kvm: Emulate CMDQ for host Mostafa Saleh
2026-10-15 20:30   ` sashiko-bot
2026-10-15 21:17     ` Mostafa Saleh
2026-10-15 20:08 ` [PATCH v9 17/25] iommu/arm-smmu-v3-kvm: Shadow stream table Mostafa Saleh
2026-10-15 20:30   ` sashiko-bot
2026-10-15 21:20     ` Mostafa Saleh
2026-10-15 20:08 ` [PATCH v9 18/25] iommu/arm-smmu-v3-kvm: Shadow STEs Mostafa Saleh
2026-10-15 20:30   ` sashiko-bot
2026-10-15 21:22     ` Mostafa Saleh
2026-10-15 20:08 ` [PATCH v9 19/25] iommu/arm-smmu-v3-kvm: Share other queues Mostafa Saleh
2026-10-15 20:29   ` sashiko-bot
2026-10-15 21:23     ` Mostafa Saleh
2026-10-15 20:08 ` [PATCH v9 20/25] iommu/arm-smmu-v3-kvm: Emulate GBPA Mostafa Saleh
2026-10-15 20:08 ` [PATCH v9 21/25] iommu/io-pgtable-arm: Support io-pgtable-arm in the hypervisor Mostafa Saleh
2026-10-15 20:26   ` sashiko-bot
2026-10-15 21:24     ` Mostafa Saleh
2026-10-15 20:08 ` [PATCH v9 22/25] iommu/arm-smmu-v3-kvm: Shadow the CPU stage-2 page table Mostafa Saleh
2026-10-15 20:32   ` sashiko-bot
2026-10-15 21:32     ` Mostafa Saleh
2026-10-15 20:08 ` [PATCH v9 23/25] iommu/arm-smmu-v3-kvm: Invalidate the SMMU TLBs Mostafa Saleh
2026-10-15 20:28   ` sashiko-bot
2026-10-15 21:35     ` Mostafa Saleh
2026-10-15 20:08 ` [PATCH v9 24/25] iommu/arm-smmu-v3-kvm: Enable nesting Mostafa Saleh
2026-10-15 20:34   ` sashiko-bot
2026-10-15 21:37     ` Mostafa Saleh
2026-10-15 20:08 ` [PATCH v9 25/25] KVM: arm64: Add documentation for pKVM DMA isolation Mostafa Saleh

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=atE9H7wWlnlqYqV3@google.com \
    --to=smostafa@google.com \
    --cc=kvmarm@lists.linux.dev \
    --cc=maz@kernel.org \
    --cc=oupton@kernel.org \
    --cc=sashiko-reviews@lists.linux.dev \
    /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