From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-ot1-f97.google.com (mail-ot1-f97.google.com [209.85.210.97]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9098A542EC7 for ; Tue, 13 Oct 2026 20:45:44 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.97 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1791924347; cv=none; b=QCYYjOATi2WwVWjFHRo/xIIJThdvuykQHguF7eOd1IIuMjZAHO7Lvo8ski07MZlrV/xnxff+hOYtNkdskqq0ERh74uWsogIZoBI2Fugr5ov+3gf9oyt8GjsTCQXQflD/Mc/jnqc+YbUyhUv2XVwJuN9dYL82B2LuZX8RBsb9GQQ= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1791924347; c=relaxed/simple; bh=vUpcsez7CgnIpw4YbzcmYEoAjaaVFIIoSzz7dzlZask=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=JQ4AmmwDeN6wW68t9sFA9I3wghrNvPGMKxWHhhv5f5NbQM5OjbD0Cs1KnSLtNVaZob0COENEAgtsrbSsG1sMBvilZgb0k2YV+hcq/iQDmEXgvXx/UNURyCxZoeg2gYLazjowESiMnZSdeM1/6him2+rHNgr1cDFI9mHo32BGjDs= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=broadcom.com; spf=fail smtp.mailfrom=broadcom.com; dkim=pass (1024-bit key) header.d=broadcom.com header.i=@broadcom.com header.b=dAdlRnSI; arc=none smtp.client-ip=209.85.210.97 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=broadcom.com Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=broadcom.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=broadcom.com header.i=@broadcom.com header.b="dAdlRnSI" Received: by mail-ot1-f97.google.com with SMTP id 46e09a7af769-823b938464fso185905a34.2 for ; Tue, 13 Oct 2026 13:45:44 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1791924343; x=1792529143; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:dkim-signature:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=Mjx/TM1iArDbn30rqgVOcHhn4GsE6BcqrxggBQfCUl4=; b=Bp5xN2vgFeOthd2MrCoFSzFzKeoy1lH1+Y/KT48q+MN8J8rQ0KgM6yXMJ4HY3KKXIX IiaouV5TJ/vVBs7wAVBjgsz9BfPRy9ZLgZ41Z63eUYf+xzvHLz6Rj1NO0sa30FIiza+S 3XqbrtlFpHguQLA7J0ez+mOR6jOMWWml+Z2ZAWnxsWu4z6F54HcSx+/Sa+4cw+9vrqBV RSGL+CVUVASxcBHfIJaCStqQp7sEQeSt2fV/IUh0n+M6aTa/vSWk/cmgFRdwdfbpLl70 WPHHqKJDsrl3opYdA3Bi2ra3BDK1QHwFHL6A37dv3xOYqRgU0wSsy7Ckb7LVo9eReD0E p1ow== X-Gm-Message-State: AFq9FYL6aBJY8dlRgLr1/bk8co9Z2Ig1Z6Xrf1gUM2H7xXXdqTlDMFJh ndkS5b+GXQxnbU0F/JRZMNvM5OINomrBoAMSLxr04LjvmKDoit6Yghod9wvoIU8MuPKgh62ilwo dRhhZlFY8MlBP13axkqaaL+gw5mpzfUgjbYnc4/ala1xUwNEmEQHHtQRMAjJjZvR+t3iqosUOcu n3kj2RgqdFkgutlsmqBk29ibcsSfjsltGEg9VYMQSmkbSamgH7AlY+es7koCGjIjsQgurteM2xf lmugz/6J8VrVyH5 X-Gm-Gg: AYBFou27yykUveW0OVSgpVBZCOKaXLbOEMkfpO4plLrfWFuE6THlE405frTtujC5Sdb AmrGiR7gIuTt0soqPlitgsVqG3hRcOLYU3FS9ofHWkUbMxYT4yxjg3hqragD3FSj5WRj6Z4hk+a bB+J5CYDYeUgaIbmTBKD6Eqw6jmsh59ZGNUBhy40BI1sNkVr58hg4XlG3VLgcRIOGrhtSLEoB0y RibhlL0ayvpfkufnD29y+Yv3hU36PJICA9BtwPw43G9ztdVpmg7kXW8JcBaTmy7tRpJn3oE5rwp 1g7M/nW/UsOyyVpCMbU4XXxCT0ORGrU5h+1ScTAH5KLAnL8KxeLmXYSjdkaikB9iXwbnA3pV2u4 rHnjGHk7/W9IE/SblBp50GqfkFHy6QfuPF0I+JTQnqABUUYEMZGeGwu0uy1VSVR75t6T0o8ECNm yldKdk7jn4AJJ6vjpBfhc18l4Uh5QatnT/rISOa1hadgM= X-Received: by 2002:a05:6830:b12:b0:82a:8e81:f619 with SMTP id 46e09a7af769-83094a8b5b6mr13813054a34.8.1791924343141; Tue, 13 Oct 2026 13:45:43 -0700 (PDT) Received: from smtp-us-east1-p01-i01-si01.dlp.protect.broadcom.com (address-144-49-247-120.dlp.protect.broadcom.com. [144.49.247.120]) by smtp-relay.gmail.com with ESMTPS id 46e09a7af769-8303aa03e2fsm133771a34.15.2026.10.13.13.45.42 for (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Tue, 13 Oct 2026 13:45:43 -0700 (PDT) X-Relaying-Domain: broadcom.com X-CFilter-Loop: Reflected Received: by mail-qt1-f200.google.com with SMTP id d75a77b69052e-5338cfe567eso72162021cf.2 for ; Tue, 13 Oct 2026 13:45:42 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=broadcom.com; s=google; t=1791924342; x=1792529142; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=Mjx/TM1iArDbn30rqgVOcHhn4GsE6BcqrxggBQfCUl4=; b=dAdlRnSIIeEdxo0s4fRVwwJqkWmEez+ti4E5lfu8EmjYHZQWHZ88PB/jOT/PhSJcy8 gvAikqFm95R1N3LwulwTCQmN+ffmMlMBWV8Q8NFcaiwTrZB4YmfmcSlavOx6FxQ+cQSS HMB+lO9cJhE726uMr/NYENzZHD1GFxSY+29GY= X-Received: by 2002:a05:622a:481b:b0:535:864:82cf with SMTP id d75a77b69052e-5359f46d548mr217193431cf.10.1791924341794; Tue, 13 Oct 2026 13:45:41 -0700 (PDT) X-Received: by 2002:a05:622a:481b:b0:535:864:82cf with SMTP id d75a77b69052e-5359f46d548mr217193031cf.10.1791924341240; Tue, 13 Oct 2026 13:45:41 -0700 (PDT) Received: from stbirv-lnx-1.igp.broadcom.net ([192.19.223.252]) by smtp.gmail.com with ESMTPSA id d75a77b69052e-535f4eee7bcsm15879231cf.30.2026.10.13.13.45.39 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 13 Oct 2026 13:45:40 -0700 (PDT) From: Florian Fainelli To: netdev@vger.kernel.org Cc: Florian Fainelli , Doug Berger , Broadcom internal kernel review list , Andrew Lunn , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Zak Kemble , Simon Horman , Ryo Takakura , linux-kernel@vger.kernel.org (open list), Nicolai Buchwitz Subject: [PATCH net v3 RESEND 6/6] net: bcmasp: fix network filter lookup and wake filter pair allocation Date: Tue, 13 Oct 2026 13:44:39 -0700 Message-Id: <20261013204439.3494046-7-florian.fainelli@broadcom.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20261013204439.3494046-1-florian.fainelli@broadcom.com> References: <20261013204439.3494046-1-florian.fainelli@broadcom.com> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-DetectorID-Processed: b00c1d49-9d2e-4205-b15f-d015386d3d5e In bcmasp_netfilt_get_init(), when looking up an existing filter (!init) for a specified location, if the filter at loc was not claimed, the previous 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. Fix this by checking only the requested location on lookup and rejecting RX_CLS_LOC_ANY when !init. In addition, harden wake filter allocation and release by ensuring wake filter pair searches stay on even boundaries where both entries are free, checking that loc + 1 is free for positioned wake filters, and validating parity and bounds on release. Fixes: c5d511c49587 ("net: bcmasp: Add support for wake on net filters") Assisted-by: LLM Signed-off-by: Florian Fainelli --- drivers/net/ethernet/broadcom/asp2/bcmasp.c | 121 +++++++++++--------- 1 file changed, 70 insertions(+), 51 deletions(-) diff --git a/drivers/net/ethernet/broadcom/asp2/bcmasp.c b/drivers/net/ethernet/broadcom/asp2/bcmasp.c index 972474893a6b..f41a79529f10 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 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, @@ -669,45 +673,55 @@ struct bcmasp_net_filter *bcmasp_netfilt_get_init(struct bcmasp_intf *intf, struct bcmasp_priv *priv = intf->parent; int i, open_index = -1; - /* Check whether we exceed the filter table capacity */ + if (!init) { + if (loc == RX_CLS_LOC_ANY || loc >= priv->num_net_filters) + return ERR_PTR(-EINVAL); + + 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); + } + 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); - - /* Initialize the loop index based on the desired location or from 0 */ - i = loc == RX_CLS_LOC_ANY ? 0 : loc; - - 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 we don't need a new filter or new filter already found */ - if (!init || open_index >= 0) - continue; - - /* 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 (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 +730,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 +751,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