From: Florian Fainelli <florian.fainelli@broadcom.com>
To: netdev@vger.kernel.org
Cc: Florian Fainelli <florian.fainelli@broadcom.com>,
Justin Chen <justin.chen@broadcom.com>,
Doug Berger <opendmb@gmail.com>,
Broadcom internal kernel review list
<bcm-kernel-feedback-list@broadcom.com>,
Andrew Lunn <andrew+netdev@lunn.ch>,
"David S. Miller" <davem@davemloft.net>,
Eric Dumazet <edumazet@google.com>,
Jakub Kicinski <kuba@kernel.org>, Paolo Abeni <pabeni@redhat.com>,
Zak Kemble <zakkemble@gmail.com>, Simon Horman <horms@kernel.org>,
Ryo Takakura <ryotkkr98@gmail.com>,
linux-kernel@vger.kernel.org (open list),
Nicolai Buchwitz <nb@tipi-net.de>
Subject: [PATCH net 6/6] net: bcmasp: fix network filter lookup and wake filter pair allocation
Date: Tue, 22 Sep 2026 15:16:30 -0700 [thread overview]
Message-ID: <20260922221630.3864427-7-florian.fainelli@broadcom.com> (raw)
In-Reply-To: <20260922221630.3864427-1-florian.fainelli@broadcom.com>
Several issues exist in bcmasp_netfilt_get_init():
1. When looking up an existing filter (!init) with a specified location
(loc != RX_CLS_LOC_ANY), if the filter at loc was not claimed, the
loop continued searching higher indices and could return an arbitrary
unrelated filter belonging to the port. This caused flow get or
delete operations on an empty rule location to return or delete an
unintended filter.
2. When allocating an unpositioned wake filter (wake_filter == true and
loc == RX_CLS_LOC_ANY), if an even index was claimed or its adjacent
odd index was claimed, the check fell through to the non-wake branch
"else if (!priv->net_filters[i].claimed)", picking an odd index and
subsequently claiming the next filter across filter pair boundaries.
3. When allocating a positioned wake filter at loc, only loc was
checked for being busy, but not loc + 1, which could overwrite an
existing filter at loc + 1.
Fix these by checking only the requested location on lookup, properly
restricting wake filter pair searches to even boundaries where both
entries are free, checking loc + 1 for positioned wake filters, and
preventing out-of-bounds release.
Fixes: c5d511c49587 ("net: bcmasp: Add support for wake on net filters")
Assisted-by: LLM
Co-developed-by: Justin Chen <justin.chen@broadcom.com>
Signed-off-by: Justin Chen <justin.chen@broadcom.com>
Co-developed-by: Florian Fainelli <florian.fainelli@broadcom.com>
Signed-off-by: Florian Fainelli <florian.fainelli@broadcom.com>
---
drivers/net/ethernet/broadcom/asp2/bcmasp.c | 127 ++++++++++++--------
1 file changed, 78 insertions(+), 49 deletions(-)
diff --git a/drivers/net/ethernet/broadcom/asp2/bcmasp.c b/drivers/net/ethernet/broadcom/asp2/bcmasp.c
index 972474893a6b..bbd152bc3a8a 100644
--- a/drivers/net/ethernet/broadcom/asp2/bcmasp.c
+++ b/drivers/net/ethernet/broadcom/asp2/bcmasp.c
@@ -511,6 +511,13 @@ static int bcmasp_netfilt_wr_to_hw(struct bcmasp_priv *priv,
return 0;
}
+static inline bool bcmasp_netfilt_is_companion(struct bcmasp_priv *priv, int i)
+{
+ return i > 0 && (i % 2) &&
+ priv->net_filters[i].wake_filter &&
+ priv->net_filters[i - 1].wake_filter;
+}
+
void bcmasp_netfilt_suspend(struct bcmasp_intf *intf)
{
struct bcmasp_priv *priv = intf->parent;
@@ -524,9 +531,7 @@ void bcmasp_netfilt_suspend(struct bcmasp_intf *intf)
priv->net_filters[i].port != intf->port)
continue;
- if (i > 0 && (i % 2) &&
- priv->net_filters[i].wake_filter &&
- priv->net_filters[i - 1].wake_filter)
+ if (bcmasp_netfilt_is_companion(priv, i))
continue;
ret = bcmasp_netfilt_wr_to_hw(priv, &priv->net_filters[i]);
@@ -556,9 +561,7 @@ int bcmasp_netfilt_get_all_active(struct bcmasp_intf *intf, u32 *rule_locs,
priv->net_filters[i].port != intf->port)
continue;
- if (i > 0 && (i % 2) &&
- priv->net_filters[i].wake_filter &&
- priv->net_filters[i - 1].wake_filter)
+ if (bcmasp_netfilt_is_companion(priv, i))
continue;
if (j == *rule_cnt)
@@ -583,9 +586,7 @@ int bcmasp_netfilt_get_active(struct bcmasp_intf *intf)
continue;
/* Skip over a wake filter pair */
- if (i > 0 && (i % 2) &&
- priv->net_filters[i].wake_filter &&
- priv->net_filters[i - 1].wake_filter)
+ if (bcmasp_netfilt_is_companion(priv, i))
continue;
cnt++;
@@ -607,6 +608,9 @@ bool bcmasp_netfilt_check_dup(struct bcmasp_intf *intf,
priv->net_filters[i].port != intf->port)
continue;
+ if (bcmasp_netfilt_is_companion(priv, i))
+ continue;
+
cur = &priv->net_filters[i].fs;
if (cur->flow_type != fs->flow_type ||
@@ -659,7 +663,7 @@ bool bcmasp_netfilt_check_dup(struct bcmasp_intf *intf,
}
/* If no network filter found, return open filter.
- * If no more open filters return NULL
+ * If no more open filters return error.
*/
struct bcmasp_net_filter *bcmasp_netfilt_get_init(struct bcmasp_intf *intf,
u32 loc, bool wake_filter,
@@ -673,41 +677,61 @@ struct bcmasp_net_filter *bcmasp_netfilt_get_init(struct bcmasp_intf *intf,
if (loc != RX_CLS_LOC_ANY && loc >= priv->num_net_filters)
return ERR_PTR(-EINVAL);
- /* If the filter location is busy (already claimed) and we are initializing
- * the filter (insertion), return a busy error code.
- */
- if (loc != RX_CLS_LOC_ANY && init && priv->net_filters[loc].claimed)
- return ERR_PTR(-EBUSY);
-
- /* We need two filters for wake-up, so we cannot use an odd filter */
- if (wake_filter && loc != RX_CLS_LOC_ANY && (loc % 2))
- return ERR_PTR(-EINVAL);
+ if (!init) {
+ if (loc != RX_CLS_LOC_ANY) {
+ if (priv->net_filters[loc].claimed &&
+ priv->net_filters[loc].port == intf->port &&
+ !bcmasp_netfilt_is_companion(priv, loc))
+ return &priv->net_filters[loc];
+ return ERR_PTR(-ENOENT);
+ }
- /* Initialize the loop index based on the desired location or from 0 */
- i = loc == RX_CLS_LOC_ANY ? 0 : loc;
+ for (i = 0; i < priv->num_net_filters; i++) {
+ if (bcmasp_netfilt_is_companion(priv, i))
+ continue;
- for ( ; i < priv->num_net_filters; i++) {
- /* Found matching network filter */
- if (!init &&
- priv->net_filters[i].claimed &&
- priv->net_filters[i].hw_index == i &&
- priv->net_filters[i].port == intf->port)
- return &priv->net_filters[i];
+ if (priv->net_filters[i].claimed &&
+ priv->net_filters[i].port == intf->port)
+ return &priv->net_filters[i];
+ }
- /* If we don't need a new filter or new filter already found */
- if (!init || open_index >= 0)
- continue;
+ return ERR_PTR(-ENOENT);
+ }
- /* Wake filter conslidates two filters to cover more bytes
- * Wake filter is open if...
- * 1. It is an even filter
- * 2. The current and next filter is not claimed
- */
- if (wake_filter && !(i % 2) && !priv->net_filters[i].claimed &&
- !priv->net_filters[i + 1].claimed)
- open_index = i;
- else if (!priv->net_filters[i].claimed)
- open_index = i;
+ /* If the filter location is busy (already claimed) and we are initializing
+ * the filter (insertion), return a busy error code.
+ */
+ if (loc != RX_CLS_LOC_ANY) {
+ if (priv->net_filters[loc].claimed)
+ return ERR_PTR(-EBUSY);
+
+ /* We need two filters for wake-up, so we cannot use an odd filter */
+ if (wake_filter) {
+ if ((loc % 2) || loc + 1 >= priv->num_net_filters)
+ return ERR_PTR(-EINVAL);
+ if (priv->net_filters[loc + 1].claimed)
+ return ERR_PTR(-EBUSY);
+ }
+ open_index = loc;
+ } else {
+ for (i = 0; i < priv->num_net_filters; i++) {
+ /* Wake filter consolidates two filters to cover more bytes.
+ * Wake filter is open if:
+ * 1. It is an even filter
+ * 2. The current and next filter is not claimed
+ */
+ if (wake_filter) {
+ if (!(i % 2) && (i + 1 < priv->num_net_filters) &&
+ !priv->net_filters[i].claimed &&
+ !priv->net_filters[i + 1].claimed) {
+ open_index = i;
+ break;
+ }
+ } else if (!priv->net_filters[i].claimed) {
+ open_index = i;
+ break;
+ }
+ }
}
if (open_index >= 0) {
@@ -716,16 +740,20 @@ struct bcmasp_net_filter *bcmasp_netfilt_get_init(struct bcmasp_intf *intf,
nfilter->port = intf->port;
nfilter->ch = intf->channel + priv->tx_chan_offset;
nfilter->hw_index = open_index;
- }
- if (wake_filter && open_index >= 0) {
- /* Claim next filter */
- priv->net_filters[open_index + 1].claimed = true;
- priv->net_filters[open_index + 1].wake_filter = true;
- nfilter->wake_filter = true;
+ if (wake_filter) {
+ /* Claim next filter */
+ priv->net_filters[open_index + 1].claimed = true;
+ priv->net_filters[open_index + 1].wake_filter = true;
+ priv->net_filters[open_index + 1].hw_index = open_index + 1;
+ priv->net_filters[open_index + 1].port = intf->port;
+ priv->net_filters[open_index + 1].ch = intf->channel +
+ priv->tx_chan_offset;
+ nfilter->wake_filter = true;
+ }
}
- return nfilter ? nfilter : ERR_PTR(-EINVAL);
+ return nfilter ? nfilter : ERR_PTR(-ENOSPC);
}
void bcmasp_netfilt_release(struct bcmasp_intf *intf,
@@ -733,7 +761,8 @@ void bcmasp_netfilt_release(struct bcmasp_intf *intf,
{
struct bcmasp_priv *priv = intf->parent;
- if (nfilt->wake_filter) {
+ if (nfilt->wake_filter && !(nfilt->hw_index % 2) &&
+ nfilt->hw_index + 1 < priv->num_net_filters) {
memset(&priv->net_filters[nfilt->hw_index + 1], 0,
sizeof(struct bcmasp_net_filter));
}
--
2.34.1
prev parent reply other threads:[~2026-09-22 22:17 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-22 22:16 [PATCH net 0/6] net: bcmasp: Collection of fixes Florian Fainelli
2026-09-22 22:16 ` [PATCH net 1/6] net: bcmasp: fix mib counters struct alignment with ethtool stats Florian Fainelli
2026-09-22 22:16 ` [PATCH net 2/6] net: bcmasp: unmap previous DMA mappings on TX map failure Florian Fainelli
2026-09-22 22:16 ` [PATCH net 3/6] net: bcmasp: validate minimum RX packet size in bcmasp_rx_poll() Florian Fainelli
2026-09-22 22:16 ` [PATCH net 4/6] net: bcmasp: fix OF node reference leak for phy_dn Florian Fainelli
2026-09-22 22:16 ` [PATCH net 5/6] net: bcmasp: account for offload header in TX short packet padding Florian Fainelli
2026-09-22 22:16 ` Florian Fainelli [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=20260922221630.3864427-7-florian.fainelli@broadcom.com \
--to=florian.fainelli@broadcom.com \
--cc=andrew+netdev@lunn.ch \
--cc=bcm-kernel-feedback-list@broadcom.com \
--cc=davem@davemloft.net \
--cc=edumazet@google.com \
--cc=horms@kernel.org \
--cc=justin.chen@broadcom.com \
--cc=kuba@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=nb@tipi-net.de \
--cc=netdev@vger.kernel.org \
--cc=opendmb@gmail.com \
--cc=pabeni@redhat.com \
--cc=ryotkkr98@gmail.com \
--cc=zakkemble@gmail.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
all inboxes | Powered by JetHome®