[PATCH net-next v2 3/4] net: dsa: qca8k: check the length of MIB autocast frames
From: Stanislaw Pal
Date: Wed Nov 04 2026 - 20:18:54 EST
qca_tag_rcv() makes only the 2 byte tag linear before it hands a MIB
frame to qca8k_mib_autocast_handler(). The handler then reads the
counters that follow the Ethernet header, up to 164 bytes on QCA833x,
straight from skb->data, without checking the frame length. A short or
non-linear frame makes it read past the packet data.
Pull the counters into the linear area before reading them. A frame
that is too short is left uncounted, so the request times out and
the caller reads the counters from the registers instead.
An LLM assistant (Claude, claude-fable-5-1) helped write the change
and this description; I reviewed both and built them with W=1 on
arm64.
Fixes: 5c957c7ca78c ("net: dsa: qca8k: add support for mib autocast in Ethernet packet")
Signed-off-by: Stanislaw Pal <kuncy7@xxxxxxxxx>
---
drivers/net/dsa/qca/qca8k-8xxx.c | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/drivers/net/dsa/qca/qca8k-8xxx.c b/drivers/net/dsa/qca/qca8k-8xxx.c
index 86b20bbc43..bc77dd45b6 100644
--- a/drivers/net/dsa/qca/qca8k-8xxx.c
+++ b/drivers/net/dsa/qca/qca8k-8xxx.c
@@ -1669,6 +1669,7 @@ static void qca8k_mib_autocast_handler(struct dsa_switch *ds, struct sk_buff *sk
struct qca8k_priv *priv = ds->priv;
const struct qca8k_mib_desc *mib;
struct mib_ethhdr *mib_ethhdr;
+ unsigned int len = 0;
__le32 *data2;
u8 port;
int i;
@@ -1691,6 +1692,16 @@ static void qca8k_mib_autocast_handler(struct dsa_switch *ds, struct sk_buff *sk
if (port != mib_eth_data->req_port)
goto exit;
+ /* Past the first 3, the counters follow the header. Leave a short
+ * frame uncounted, so that the request times out and the caller
+ * reads the registers instead.
+ */
+ for (i = 3; i < priv->info->mib_count; i++)
+ len += ar8327_mib[i].size * sizeof(u32);
+ if (!pskb_may_pull(skb, len))
+ goto unlock;
+
+ mib_ethhdr = (struct mib_ethhdr *)skb_mac_header(skb);
data2 = (__le32 *)skb->data;
for (i = 0; i < priv->info->mib_count; i++) {
--
2.43.0