From: sashiko-bot@kernel.org
To: "Zhi Wang" <zhiw@nvidia.com>
Cc: linux-pci@vger.kernel.org, ojeda@kernel.org
Subject: Re: [PATCH v4 1/1] rust: pci: add extended capability and SR-IOV support
Date: Tue, 14 Jul 2026 17:20:03 +0000 [thread overview]
Message-ID: <20260714172004.306FA1F000E9@smtp.kernel.org> (raw)
In-Reply-To: <20260714165827.2937960-2-zhiw@nvidia.com>
Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
- [Critical] The `ConfigSpace` abstraction cannot store a capability offset, causing extended capability reads/writes to silently target the standard PCI header.
- [High] Data structure layout bug conflates `func_dep_link` with a reserved hardware register.
- [High] Double-fetch of the VF BAR register in `read_vf_bar64` introduces a Time-of-Check to Time-of-Use (TOCTOU) vulnerability with untrusted hardware.
--
--- Patch [1]: [PATCH v4 1/1] rust: pci: add extended capability and SR-IOV support ---
commit 12bd7c1ee008a72446697b452c0ce723422b22e0
Author: Zhi Wang <zhiw@nvidia.com>
rust: pci: add extended capability and SR-IOV support
Rust PCI drivers have no typed interface for locating and accessing PCIe
extended capabilities. The SR-IOV extended capability describes VF topology
and VF BARs. Expose this information through the Rust PCI abstraction so
drivers can use the existing typed configuration-space accessors.
Link: https://lore.kernel.org/rust-for-linux/20260409185254.3869808-1-zhiw@nvidia.com/
> diff --git a/rust/kernel/pci/cap.rs b/rust/kernel/pci/cap.rs
> new file mode 100644
> index 0000000000000..a37c96d3d5395
> --- /dev/null
> +++ b/rust/kernel/pci/cap.rs
> @@ -0,0 +1,209 @@
[ ... ]
> + pub fn find_ext_capability<C: ExtCapability>(&self) -> Result<ConfigSpace<'a, C>> {
> + let offset = usize::from(
> + // SAFETY: `self.pdev` is valid by the type invariant of `ConfigSpace`.
> + unsafe {
> + bindings::pci_find_ext_capability(self.pdev.as_raw(), i32::from(C::ID.as_raw()))
> + },
> + );
> +
> + if offset == 0 {
> + return Err(ENODEV);
> + }
> +
> + let size = self.calculate_ext_cap_size(offset);
> +
> + let base = ConfigSpaceBackend::as_ptr(*self)
> + .cast::<u8>()
> + .wrapping_add(offset);
> + let ptr = Region::<0>::ptr_try_from_raw_parts_mut(base, size)?;
> +
> + // SAFETY: `offset` was returned by `pci_find_ext_capability`, and
> + // `calculate_ext_cap_size` bounds `ptr` at the next capability or the end of the extended
> + // configuration space. `ptr_try_from_raw_parts_mut` verified the region layout.
> + let capability = unsafe { ConfigSpaceBackend::project_view(*self, ptr) };
> +
> + capability.try_cast::<C>()
> + }
[Severity: Critical]
Does the ConfigSpace abstraction have a way to store the runtime capability
base offset?
It looks like ConfigSpace only holds a pdev reference and a PhantomData marker,
physically lacking a field to store the runtime capability base offset.
If the Io trait implementation for ConfigSpace returns 0 for the address,
wouldn't reading or writing to this view silently target the standard PCI
configuration registers at offset 0, ignoring the capability's actual offset?
[ ... ]
> +/// SR-IOV register layout per PCIe spec (64 bytes starting at cap offset).
> +#[repr(C)]
> +#[derive(FromBytes, IntoBytes)]
> +pub struct ExtSriovRegs {
> + /// Extended capability header.
> + pub header: u32,
> + /// SR-IOV capabilities.
> + pub cap: u32,
> + /// SR-IOV control.
> + pub ctrl: u16,
> + /// SR-IOV status.
> + pub status: u16,
> + /// Initial VFs.
> + pub initial_vfs: u16,
> + /// Total VFs.
> + pub total_vfs: u16,
> + /// Number of VFs.
> + pub num_vfs: u16,
> + /// Function dependency link.
> + pub func_dep_link: u16,
[Severity: High]
Is it safe to declare the 8-bit Function Dependency Link register as a
16-bit field?
This conflates it with the adjacent reserved byte at offset 0x13. On
little-endian architectures, reading this might pull non-zero reserved bits
into the upper 8 bits. Furthermore, writing it could overwrite the reserved
bits, potentially corrupting hardware state.
> + /// First VF offset.
> + pub vf_offset: u16,
> + /// VF stride.
> + pub vf_stride: u16,
[ ... ]
> +impl ConfigSpace<'_, ExtSriovRegs> {
> + /// Returns `true` if the VF BAR at `bar_index` is a 64-bit memory BAR.
> + #[inline]
> + pub fn is_vf_bar_64bit(&self, bar_index: usize) -> Result<bool> {
> + if bar_index >= NUM_VF_BARS {
> + return Err(EINVAL);
> + }
> +
> + let bar = crate::io_read!(*self, .vf_bar[try: bar_index]);
> +
> + Ok(bar & bindings::PCI_BASE_ADDRESS_SPACE == 0
> + && bar & bindings::PCI_BASE_ADDRESS_MEM_TYPE_MASK
> + == bindings::PCI_BASE_ADDRESS_MEM_TYPE_64)
> + }
> +
> + /// Reads a 64-bit VF BAR from two consecutive 32-bit slots.
> + #[inline]
> + pub fn read_vf_bar64(&self, bar_index: usize) -> Result<u64> {
> + if !self.is_vf_bar_64bit(bar_index)? {
[Severity: High]
Does this introduce a Time-of-Check to Time-of-Use (TOCTOU) issue when
dealing with untrusted hardware?
is_vf_bar_64bit() performs a PCI config space read to check if the BAR is
a 64-bit memory type. Immediately after, read_vf_bar64() performs a second
read on the exact same register to extract the lower 32 bits:
> + return Err(EINVAL);
> + }
> +
> + let high_index = bar_index.checked_add(1).ok_or(EINVAL)?;
> + if high_index >= NUM_VF_BARS {
> + return Err(EINVAL);
> + }
> +
> + let low = crate::io_read!(*self, .vf_bar[try: bar_index]);
Could a malicious device return a 64-bit indicator during the first read,
but a different 32-bit payload during the second read? It might be safer
to read the register exactly once, validate the read value, and then use
that same value.
> + let high = crate::io_read!(*self, .vf_bar[try: high_index]);
> + Ok((u64::from(high) << 32) | u64::from(low))
> + }
> +}
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260714165827.2937960-2-zhiw@nvidia.com?part=1
prev parent reply other threads:[~2026-07-14 17:20 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-14 16:58 [PATCH v4 0/1] Rust PCI capability infrastructure and SR-IOV support Zhi Wang
2026-07-14 16:58 ` [PATCH v4 1/1] rust: pci: add extended capability " Zhi Wang
2026-07-14 17:20 ` sashiko-bot [this message]
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=20260714172004.306FA1F000E9@smtp.kernel.org \
--to=sashiko-bot@kernel.org \
--cc=linux-pci@vger.kernel.org \
--cc=ojeda@kernel.org \
--cc=sashiko-reviews@lists.linux.dev \
--cc=zhiw@nvidia.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