Linux kernel and device drivers for NXP i.MX platforms
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: wei.fang@oss.nxp.com
Cc: imx@lists.linux.dev, Frank.Li@kernel.org
Subject: Re: [PATCH v3 net-next 12/14] net: enetc: remove redundant num_vsi field from enetc_port_caps
Date: Sat, 04 Jul 2026 10:43:46 +0000	[thread overview]
Message-ID: <20260704104346.D7A561F00A3D@smtp.kernel.org> (raw)
In-Reply-To: <20260703101328.550714-13-wei.fang@oss.nxp.com>

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] Replacing hardware `num_vsi` with `total_vfs` breaks the structural bounds of MSI-X vector allocation per SI, causing bitwise truncation and starving the PF of interrupts when SR-IOV is disabled.
- [Medium] Replacing hardware-bounded `caps.num_vsi` with `total_vfs` derived from untrusted PCIe SR-IOV config space leads to out-of-bounds MMIO accesses and out-of-bounds bit shifts.
--

commit aa0b3c99b21e1eb4ed8e7824db6286ae200b0d9e
Author: Wei Fang <wei.fang@nxp.com>

net: enetc: remove redundant num_vsi field from enetc_port_caps

The num_vsi field in struct enetc_port_caps is populated by reading the
NUM_VSI field of the ECAPR1 register, which reports the number of VSIs
supported by the ENETC4 port. When CONFIG_PCI_IOV is enabled, this value
matches the total number of VFs reported by the PCI SR-IOV capability,
which is already stored in pf->total_vfs during probe via
pci_sriov_get_totalvfs(). When CONFIG_PCI_IOV is disabled,
pci_sriov_get_totalvfs() returns 0, but this is benign since
pci_enable_sriov() is also stubbed to return -ENODEV, so no VF can be
created, and enetc4_enable_all_si() only enables the PF SI (PSI).

Since pf->total_vfs already reflects the number of VFs that can actually
be used, and is the established convention in the sibling FSL_ENETC PF
driver, there is no need to read and cache num_vsi separately in the port
capabilities structure. Remove the num_vsi field from enetc_port_caps and
the associated ECAPR1_NUM_VSI macro, and replace all uses of
pf->caps.num_vsi with pf->total_vfs in the ring allocation, MSI-X
configuration, SI enable, and debugfs code paths.

> diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_debugfs.c b/drivers/net/ethernet/freescale/enetc/enetc4_debugfs.c
> index be378bf8f74d1..5029038bf99fa 100644
> --- a/drivers/net/ethernet/freescale/enetc/enetc4_debugfs.c
> +++ b/drivers/net/ethernet/freescale/enetc/enetc4_debugfs.c
[ ... ]
> @@ -28,17 +28,14 @@ static void enetc_show_si_mac_hash_filter(struct seq_file *s, int i)
>  
>  static int enetc_mac_filter_show(struct seq_file *s, void *data)
>  {
> -	struct enetc_si *si = s->private;
> -	struct enetc_hw *hw = &si->hw;
> +	struct enetc_pf *pf = enetc_si_priv(s->private);
> +	struct enetc_hw *hw = &pf->si->hw;
> +	int num_si = pf->total_vfs + 1;

[Severity: Medium]
Could the unconstrained num_si derived from pf->total_vfs cause undefined
behavior in the loops further down in this function?

The original code used caps.num_vsi, which was structurally capped by a 4-bit
hardware register mask. The value total_vfs is read from
pci_sriov_get_totalvfs(), which returns an unvalidated 16-bit PCIe
configuration value.

An arbitrarily large total_vfs from a misconfigured or malicious firmware would
cause PSIPMMR_SI_MAC_MP(i) (which evaluates to BIT(i + 16)) to shift beyond
the bounds of its type when evaluating:
str_enabled_disabled(PSIPMMR_SI_MAC_MP(i) & val).

>  	struct maft_entry_data maft;
>  	struct ntmp_user *user;
> -	struct enetc_pf *pf;
>  	u32 val, entry_id;
> -	int i, num_si;
>  	int err = 0;
> -
> -	pf = enetc_si_priv(si);
> -	num_si = pf->caps.num_vsi + 1;
> +	int i;
[ ... ]
> diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
> index cab79f81d6fe0..8d536a3831e3a 100644
> --- a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
> +++ b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
[ ... ]
> @@ -255,34 +254,35 @@ static void enetc4_default_rings_allocation(struct enetc_pf *pf)
>  {
>  	struct enetc_hw *hw = &pf->si->hw;
>  	u32 num_rx_bdr, num_tx_bdr, val;
> +	int num_vfs = pf->total_vfs;
>  	u32 vf_tx_bdr, vf_rx_bdr;
>  	int i, rx_rem, tx_rem;
>  
[ ... ]
> -	for (i = 0; i < pf->caps.num_vsi; i++) {
> +	for (i = 0; i < num_vfs; i++) {
>  		vf_tx_bdr = (i < tx_rem) ? num_tx_bdr + 1 : num_tx_bdr;
>  		vf_rx_bdr = (i < rx_rem) ? num_rx_bdr + 1 : num_rx_bdr;
>  		val = enetc4_psicfgr0_val_construct(true, vf_tx_bdr, vf_rx_bdr);
> -		enetc_port_wr(hw, ENETC4_PSICFGR0(i + 1), val);
> +		enetc_port_wr(hw, ENETC4_PSICFGR0(i + 1), val);

[Severity: Medium]
Could this result in out-of-bounds MMIO accesses if a misconfigured or malicious
PCIe device firmware reports a total_vfs value larger than the actual hardware
capacity (e.g., > 15) in its SR-IOV Extended Capability?

Similar to the debugfs issue above, replacing the hardware-capped caps.num_vsi
with an unvalidated total_vfs causes this unconstrained loop to write past the
instantiated ENETC4_PSICFGR0 register bounds.

>  	}
>  }
[ ... ]
> @@ -299,26 +299,25 @@ static void enetc4_allocate_si_rings(struct enetc_pf *pf)
>  static void enetc4_set_si_msix_num(struct enetc_pf *pf)
>  {
>  	struct enetc_hw *hw = &pf->si->hw;
> -	int i, num_msix, total_si;
> +	int num_si = pf->total_vfs + 1;
> +	int i, num_msix;
>  	u32 val;
>  
> -	total_si = pf->caps.num_vsi + 1;
> -
> -	num_msix = pf->caps.num_msix / total_si +
> -		   pf->caps.num_msix % total_si - 1;
> +	num_msix = pf->caps.num_msix / num_si +
> +		   pf->caps.num_msix % num_si - 1;
>  	val = num_msix & PSICFGR2_NUM_MSIX;
>  	enetc_port_wr(hw, ENETC4_PSICFGR2(0), val);

[Severity: High]
Can this cause bitwise truncation and starve the PF of interrupts when SR-IOV
is disabled?

If CONFIG_PCI_IOV is disabled, pf->total_vfs evaluates to 0, making
num_si = 1. The driver will then attempt to allocate all available hardware
MSI-X vectors to the PF (num_msix = pf->caps.num_msix - 1).

If the hardware supports more than 64 MSI-X vectors, num_msix will exceed the
6-bit width (max 63) of the hardware register field PSICFGR2_NUM_MSIX.
The bitwise AND operator & PSICFGR2_NUM_MSIX truncates the value instead of
clamping it (e.g., 64 & 0x3F == 0).

This programs the PF to receive 0 vectors (effectively 1 vector due to the N-1
encoding), starving it of necessary interrupts. The previous implementation
divided by pf->caps.num_vsi + 1, which structurally guarded against this
large allocation.

>  
> -	num_msix = pf->caps.num_msix / total_si - 1;
> +	num_msix = pf->caps.num_msix / num_si - 1;
>  	val = num_msix & PSICFGR2_NUM_MSIX;
> -	for (i = 0; i < pf->caps.num_vsi; i++)
> +	for (i = 0; i < pf->total_vfs; i++)
>  		enetc_port_wr(hw, ENETC4_PSICFGR2(i + 1), val);
>  }

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260703101328.550714-1-wei.fang@oss.nxp.com?part=12

  reply	other threads:[~2026-07-04 10:43 UTC|newest]

Thread overview: 25+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-03 10:13 [PATCH v3 net-next 00/14] net: enetc: cleanups and improvements wei.fang
2026-07-03 10:13 ` [PATCH v3 net-next 01/14] net: enetc: extract common helpers for MAC promiscuous mode setting wei.fang
2026-07-03 10:13 ` [PATCH v3 net-next 02/14] net: enetc: extract common helpers for MAC hash filter configuration wei.fang
2026-07-04 10:43   ` sashiko-bot
2026-07-03 10:13 ` [PATCH v3 net-next 03/14] net: enetc: convert ndo_set_rx_mode() to ndo_set_rx_mode_async() wei.fang
2026-07-03 10:13 ` [PATCH v3 net-next 04/14] net: enetc: improve MAFT entry management with bitmap tracking wei.fang
2026-07-03 10:13 ` [PATCH v3 net-next 05/14] net: enetc: use PCI device name for debugfs directory wei.fang
2026-07-03 10:13 ` [PATCH v3 net-next 06/14] net: enetc: simplify enetc4_set_port_speed() wei.fang
2026-07-03 10:13 ` [PATCH v3 net-next 07/14] net: enetc: differentiate phylink capabilities for pseudo-MAC and standalone MAC wei.fang
2026-07-04 10:43   ` sashiko-bot
2026-07-06  1:25     ` Wei Fang (OSS)
2026-07-03 10:13 ` [PATCH v3 net-next 08/14] net: enetc: remove invalid code from enetc4_pl_mac_link_up() wei.fang
2026-07-03 10:13 ` [PATCH v3 net-next 09/14] net: enetc: open-code enetc4_set_default_si_vlan_promisc() wei.fang
2026-07-03 10:13 ` [PATCH v3 net-next 10/14] net: enetc: refactor SI VLAN promiscuous mode configuration wei.fang
2026-07-04 10:43   ` sashiko-bot
2026-07-06  1:42     ` Wei Fang (OSS)
2026-07-06  1:45     ` Wei Fang (OSS)
2026-07-03 10:13 ` [PATCH v3 net-next 11/14] net: enetc: move enetc_set_si_vlan_promisc() to enetc_pf_common.c wei.fang
2026-07-03 10:13 ` [PATCH v3 net-next 12/14] net: enetc: remove redundant num_vsi field from enetc_port_caps wei.fang
2026-07-04 10:43   ` sashiko-bot [this message]
2026-07-06  2:27     ` Wei Fang (OSS)
2026-07-03 10:13 ` [PATCH v3 net-next 13/14] net: enetc: use alloc_etherdev_mqs() to create netdev for VF driver wei.fang
2026-07-04 10:43   ` sashiko-bot
2026-07-03 10:13 ` [PATCH v3 net-next 14/14] net: enetc: use kzalloc_flex() for enetc_psfp_gate allocation wei.fang
2026-07-04 10:43   ` 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=20260704104346.D7A561F00A3D@smtp.kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=Frank.Li@kernel.org \
    --cc=imx@lists.linux.dev \
    --cc=sashiko-reviews@lists.linux.dev \
    --cc=wei.fang@oss.nxp.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