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 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.