From: sashiko-bot@kernel.org
To: "Leon Romanovsky" <leon@kernel.org>
Cc: linux-input@vger.kernel.org, linux-usb@vger.kernel.org,
linux-pci@vger.kernel.org, dmitry.torokhov@gmail.com
Subject: Re: [PATCH v2 18/19] PCI: Replace untrusted state with device trust
Date: Tue, 10 Nov 2026 07:35:25 +0000 [thread overview]
Message-ID: <sashiko-outbox-206518@kernel.org> (raw)
In-Reply-To: <20261109-device-trust-core-v2-18-3b12d9a9f861@nvidia.com>
Thank you for your contribution! Sashiko AI review found 5 potential
issues to consider:
- [High] PCI: broken adversarial trust inheritance in
pci_set_default_trust_policy()
- [High] PCI: default trust policy overwrites adversarial default on
removable devices
- [Medium] PCI: pci_enable_acs() and pci_ats_init() break
disabled-to-full trust policy
- [Medium] PCI: pci_dev_ats_permitted() drops PCI_ACS_TB after full
authorization
- [Medium] PCI: of_create_pci_dev() skips pci_set_default_trust_policy()
before ATS init
--
commit 7c55633025e040b3c2b6b2f31a6d205ea496c0f7
Author: Leon Romanovsky <leon@kernel.org>
PCI: Replace untrusted state with device trust
This commit replaces pci_dev::untrusted with the generic device trust policy
and trust level helpers across the PCI and IOMMU subsystems.
> diff --git a/drivers/pci/ats.c b/drivers/pci/ats.c
> index 9cb23780093dd..c8c96acc26343 100644
> --- a/drivers/pci/ats.c
> +++ b/drivers/pci/ats.c
> @@ -21,7 +21,7 @@ void pci_ats_init(struct pci_dev *dev)
> {
> int pos;
>
> - if (pci_ats_disabled() || dev->untrusted)
> + if (pci_ats_disabled() || pci_dev_default_is_restricted(dev))
> return;
>
> pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ATS);
> @@ -40,7 +40,7 @@ void pci_ats_init(struct pci_dev *dev)
> */
> bool pci_ats_supported(struct pci_dev *dev)
> {
> - if (!dev->ats_cap || dev->untrusted)
> + if (!dev->ats_cap)
> return false;
>
> if (dev->is_virtfn)
> diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
> index 7c6f2aba81443..b08adba03f96b 100644
> --- a/drivers/pci/pci.c
> +++ b/drivers/pci/pci.c
> @@ -1016,8 +1016,9 @@ static void pci_std_enable_acs(struct pci_dev *dev, struct pci_acs *caps)
> /* Upstream Forwarding */
> caps->ctrl |= (dev->acs_capabilities & PCI_ACS_UF);
>
> - /* Enable Translation Blocking for external devices and noats */
> - if (pci_ats_disabled() || dev->external_facing || dev->untrusted)
> + /* Enable Translation Blocking when ATS is unavailable or restricted. */
> + if (pci_ats_disabled() || dev->external_facing ||
> + !pci_dev_ats_permitted(dev))
> caps->ctrl |= (dev->acs_capabilities & PCI_ACS_TB);
> }
[Severity: Medium]
Does a device that starts with DEVICE_TRUST_POLICY_DISABLED (for example via
device_trust.default=disabled before initrd authorization or a driver trust
rule) keep ATS disabled and PCI_ACS_TB enabled even after it is authorized for
DEVICE_TRUST_FULL?
During pci_device_add(), pci_ats_init() sees pci_dev_default_is_restricted()
return true and skips initializing dev->ats_cap; nothing re-runs
pci_ats_init() when the device later transitions to DEVICE_TRUST_FULL.
Likewise, device_add() -> iommu_probe_device() -> pci_dma_configure() ->
pci_enable_acs() runs while the device is still unbound
(DEVICE_TRUST_DISABLED), so !pci_dev_ats_permitted(dev) is true and
pci_std_enable_acs() (as well as pci_quirk_enable_intel_spt_pch_acs()) sets
PCI_ACS_TB in hardware. When really_probe() later sets DEVICE_TRUST_FULL and
calls pci_dma_configure() -> pci_enable_acs() a second time, pci_enable_acs()
reads the existing PCI_ACS_CTRL register value into caps.ctrl and only ORs
bits into it, never clearing PCI_ACS_TB.
> diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
> index 5b6960bbb35bc..607569c31b5b9 100644
> --- a/drivers/pci/probe.c
> +++ b/drivers/pci/probe.c
> @@ -1738,24 +1738,24 @@ static void set_pcie_cxl(struct pci_dev *dev)
>
> }
>
> -static void set_pcie_untrusted(struct pci_dev *dev)
> +static void pci_set_default_trust_policy(struct pci_dev *dev)
> {
> - struct pci_dev *parent = pci_upstream_bridge(dev);
> + struct pci_dev *parent = pci_physfn(dev);
> +
> + if (parent == dev)
> + parent = pci_upstream_bridge(dev);
>
> if (!parent)
> return;
> - /*
> - * If the upstream bridge is untrusted we treat this device as
> - * untrusted as well.
> - */
> - if (parent->untrusted) {
> - dev->untrusted = true;
> +
> + if (device_policy_is_adversarial(&parent->dev)) {
> + dev->dev.trust_policy = DEVICE_TRUST_POLICY_ADVERSARY;
> return;
> }
>
> if (arch_pci_dev_is_removable(dev)) {
> - pci_dbg(dev, "marking as untrusted\n");
> - dev->untrusted = true;
> + pci_dbg(dev, "setting adversarial trust policy\n");
> + dev->dev.trust_policy = DEVICE_TRUST_POLICY_ADVERSARY;
> }
> }
[Severity: High]
Can downstream devices behind a removable PCIe switch or SR-IOV VFs on a
removable PF lose their adversarial default policy when the parent's
trust_policy is overridden?
In pci_setup_device(), device_trust_init(&dev->dev) runs on the parent bridge
before child buses are scanned (or before SR-IOV VFs are created). If the
parent port or PF has its trust_policy changed to disabled or full (for
example via device_trust.default=disabled, a per-device rule, or sysfs),
device_policy_is_adversarial(&parent->dev) is false for its children. On x86
ACPI systems, arch_pci_dev_is_removable() only returns true for the switch
upstream port directly beneath an integrated USB4/Thunderbolt root port and
returns false for the switch's downstream ports, endpoints below them, and
VFs:
arch/x86/pci/acpi.c:arch_pci_dev_is_removable() {
...
/* Anything directly behind a "usb4-host-interface" is tunneled */
if (pcie_has_usb4_host_interface(parent))
return true;
if (pcie_switch_directly_under(root, pdev))
return false;
...
}
Those child devices therefore stay at DEVICE_TRUST_POLICY_DEFAULT and resolve
to DEVICE_TRUST_FULL, bypassing IOMMU DMA domain enforcement, ATS and ACS
restrictions, and SWIOTLB bounce buffering. Running pci_set_removable(dev)
before pci_set_default_trust_policy(dev) and checking dev_is_removable() would
preserve the hardware removability state across parent policy overrides.
> @@ -2082,7 +2082,7 @@ int pci_setup_device(struct pci_dev *dev)
>
> set_pcie_cxl(dev);
>
> - set_pcie_untrusted(dev);
> + pci_set_default_trust_policy(dev);
> device_trust_init(&dev->dev);
>
> /* "Unknown power state" */
[Severity: Medium]
On PowerPC and SPARC systems where of_create_pci_dev() creates PCI devices
directly without calling pci_setup_device(), does pci_ats_init() run before
the device trust policy is initialized?
of_create_pci_dev() calls pci_device_add(), which runs
pci_init_capabilities() -> pci_ats_init() before device_add() calls
device_trust_init(), and never calls pci_set_default_trust_policy(). Because
pci_ats_supported() no longer checks the device state at runtime, dev->ats_cap
is populated while trust_policy is still DEVICE_TRUST_POLICY_DEFAULT, leaving
ATS enabled even when a boot trust policy restricts the device.
> diff --git a/include/linux/pci.h b/include/linux/pci.h
> index aa3765a20a96c..087c63b177c85 100644
> --- a/include/linux/pci.h
> +++ b/include/linux/pci.h
[ ... ]
> @@ -616,6 +608,28 @@ static inline struct pci_dev *to_pci_dev(const struct device *dev)
> {
> return container_of(dev, struct pci_dev, dev);
> }
> +
> +static inline bool
> +pci_dev_default_is_restricted(const struct pci_dev *pdev)
> +{
> + enum device_trust_policy policy = READ_ONCE(pdev->dev.trust_policy);
> +
> + return policy == DEVICE_TRUST_POLICY_DISABLED ||
> + policy == DEVICE_TRUST_POLICY_ADVERSARY;
> +}
[Severity: High]
If a removable PCI device is configured with an explicit "default" trust
policy (via device_trust=, device_trust.driver=, or sysfs trust_policy), does
that overwrite DEVICE_TRUST_POLICY_ADVERSARY with DEVICE_TRUST_POLICY_DEFAULT
and grant the external device DEVICE_TRUST_FULL?
In pci_setup_device(), device_trust_init() runs after
pci_set_default_trust_policy() and overwrites dev->dev.trust_policy with
DEVICE_TRUST_POLICY_DEFAULT when a per-device default rule matches. Because
pci_dev_default_is_restricted() only checks for DISABLED and ADVERSARY, and
pci_bus_type does not implement .trust_resolve, DEVICE_TRUST_POLICY_DEFAULT
bypasses pci_dev_default_is_restricted() during discovery and resolves to
DEVICE_TRUST_FULL in __device_trust_prepare() at bind time.
> +static inline bool pci_dev_ats_permitted(const struct pci_dev *pdev)
> +{
> + enum device_trust_level level = device_get_trust_level(&pdev->dev);
> + enum device_trust_policy policy = READ_ONCE(pdev->dev.trust_policy);
> +
> + if (level == DEVICE_TRUST_DISABLED)
> + return policy != DEVICE_TRUST_POLICY_ADVERSARY &&
> + policy != DEVICE_TRUST_POLICY_DISABLED;
> +
> + return level == DEVICE_TRUST_FULL;
> +}
[Severity: Medium]
Can a device discovered with DEVICE_TRUST_POLICY_DISABLED lose PCI_ACS_TB in
hardware after being authorized for DEVICE_TRUST_FULL and undergoing a PCI
reset or D3cold transition?
At discovery, pci_ats_init() skips setting dev->ats_cap and pci_enable_acs()
sets PCI_ACS_TB because !pci_dev_ats_permitted(dev) is true. Once the device
is authorized and bound with DEVICE_TRUST_FULL, pci_dev_ats_permitted()
returns true even though dev->ats_cap is 0. Because ACS registers are not
saved in saved_cap_space, a subsequent reset or D3cold resume clears the
hardware register and runs pci_restore_state() -> pci_enable_acs() ->
pci_std_enable_acs(), which sees pci_dev_ats_permitted() return true and
leaves PCI_ACS_TB cleared.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261109-device-trust-core-v2-0-3b12d9a9f861@nvidia.com?part=18
next prev parent reply other threads:[~2026-11-10 7:35 UTC|newest]
Thread overview: 52+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-09 7:33 [PATCH v2 00/19] driver core: Authorize device trust before driver binding Leon Romanovsky
2026-11-09 7:33 ` [PATCH v2 01/19] Input: gameport - attach manual drivers through the driver core Leon Romanovsky
2026-11-09 10:06 ` driver core: Authorize device trust before driver binding bluez.test.bot
2026-11-10 7:35 ` [PATCH v2 01/19] Input: gameport - attach manual drivers through the driver core sashiko-bot
2026-11-09 7:33 ` [PATCH v2 02/19] wifi: mac80211_hwsim: lock device for manual driver binding Leon Romanovsky
2026-11-10 7:35 ` sashiko-bot
2026-11-09 7:33 ` [PATCH v2 03/19] USB: Lock registered interfaces during " Leon Romanovsky
2026-11-10 7:35 ` sashiko-bot
2026-11-10 14:19 ` Leon Romanovsky
2026-11-09 7:33 ` [PATCH v2 04/19] USB: Release interface claims refused during registration Leon Romanovsky
2026-11-10 7:35 ` sashiko-bot
2026-11-10 14:23 ` Leon Romanovsky
2026-11-09 7:33 ` [PATCH v2 05/19] PNP: Attach card devices through the driver core Leon Romanovsky
2026-11-10 7:35 ` sashiko-bot
2026-11-09 7:33 ` [PATCH v2 06/19] cdx: Propagate DMA configuration errors Leon Romanovsky
2026-11-10 7:35 ` sashiko-bot
2026-11-09 7:33 ` [PATCH v2 07/19] driver core: Report deferred probes through sysfs drivers_probe Leon Romanovsky
2026-11-10 7:35 ` sashiko-bot
2026-11-09 7:33 ` [PATCH v2 08/19] driver core: Add a compatibility API for manual driver attachment Leon Romanovsky
2026-11-10 7:35 ` sashiko-bot
2026-11-09 7:33 ` [PATCH v2 09/19] Input: serio - use the compatibility driver attachment API Leon Romanovsky
2026-11-10 7:35 ` sashiko-bot
2026-11-10 14:29 ` Leon Romanovsky
2026-11-09 7:33 ` [PATCH v2 10/19] net: phy: Use " Leon Romanovsky
2026-11-09 13:45 ` Andrew Lunn
2026-11-10 7:39 ` Leon Romanovsky
2026-11-10 14:31 ` Andrew Lunn
2026-11-10 14:58 ` Leon Romanovsky
2026-11-10 7:35 ` sashiko-bot
2026-11-09 7:33 ` [PATCH v2 11/19] driver core: Introduce a generic device trust level Leon Romanovsky
2026-11-10 7:35 ` sashiko-bot
2026-11-10 15:12 ` Leon Romanovsky
2026-11-09 7:33 ` [PATCH v2 12/19] driver core: Expose device trust authorization interfaces Leon Romanovsky
2026-11-10 7:35 ` sashiko-bot
2026-11-09 7:33 ` [PATCH v2 13/19] driver core: Accept device trust policy on the kernel command line Leon Romanovsky
2026-11-10 7:35 ` sashiko-bot
2026-11-09 7:33 ` [PATCH v2 14/19] driver core: Accept device trust policy by driver name Leon Romanovsky
2026-11-10 7:35 ` sashiko-bot
2026-11-09 7:33 ` [PATCH v2 15/19] driver core: Expose committed device trust level Leon Romanovsky
2026-11-10 7:35 ` sashiko-bot
2026-11-09 7:33 ` [PATCH v2 16/19] driver core: Cover trust authorization and binding with KUnit Leon Romanovsky
2026-11-10 7:35 ` sashiko-bot
2026-11-09 7:33 ` [PATCH v2 17/19] driver core: Document trust admission and initrd authorization Leon Romanovsky
2026-11-10 7:35 ` sashiko-bot
2026-11-09 7:33 ` [PATCH v2 18/19] PCI: Replace untrusted state with device trust Leon Romanovsky
2026-11-09 13:53 ` Robin Murphy
2026-11-10 12:22 ` Leon Romanovsky
2026-11-10 14:25 ` Jason Gunthorpe
2026-11-10 14:34 ` Leon Romanovsky
2026-11-10 7:35 ` sashiko-bot [this message]
2026-11-09 7:33 ` [PATCH v2 19/19] USB: Authorize devices and interfaces through " Leon Romanovsky
2026-11-10 7:35 ` sashiko-bot
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=sashiko-outbox-206518@kernel.org \
--to=sashiko-bot@kernel.org \
--cc=dmitry.torokhov@gmail.com \
--cc=leon@kernel.org \
--cc=linux-input@vger.kernel.org \
--cc=linux-pci@vger.kernel.org \
--cc=linux-usb@vger.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.