From: Stanislaw Pal <kuncy7@gmail.com>
To: Christian Marangi <ansuelsmth@gmail.com>,
Andrew Lunn <andrew@lunn.ch>, Vladimir Oltean <olteanv@gmail.com>
Cc: "David S . Miller" <davem@davemloft.net>,
Eric Dumazet <edumazet@kernel.org>,
Jakub Kicinski <kuba@kernel.org>, Paolo Abeni <pabeni@redhat.com>,
Yongzhao Chen <yongzhao.derek@gmail.com>,
netdev@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [PATCH net-next v2 4/4] net: dsa: qca8k: bound the data of a management ack frame
Date: Wed, 4 Nov 2026 22:07:57 +0100 [thread overview]
Message-ID: <20261104210757.467964-5-kuncy7@gmail.com> (raw)
In-Reply-To: <20261104210757.467964-1-kuncy7@gmail.com>
qca8k_rw_reg_ack_handler() answers a management read by copying the
data that follows the Ethernet header into mgmt_eth_data->data. It
trusts the frame for both the length and the layout: the length field
of the frame allows up to 32 bytes while the buffer holds 16, so a
frame announcing more than three registers writes past the buffer into
the fields that follow it in qca8k_priv; and qca_tag_rcv() made only
the 2 byte tag linear, so the copy reads skb->data without checking
that the frame has the bytes it announces. The handler runs for every
ack frame, whatever its sequence number.
Size the buffer to what a management frame can carry, and pull the
announced data into the linear area before reading it. A frame that
is too short is left unacknowledged, so the read fails and the caller
falls back to MDIO.
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. The management path was exercised on a QCA8337 behind an
IPQ5018 (GL.iNet GL-B3000) with tag_qca.
Fixes: 90386223f44e ("net: dsa: qca8k: add support for larger read/write size with mgmt Ethernet")
Signed-off-by: Stanislaw Pal <kuncy7@gmail.com>
---
drivers/net/dsa/qca/qca8k-8xxx.c | 21 ++++++++++++++++-----
drivers/net/dsa/qca/qca8k.h | 3 ++-
2 files changed, 18 insertions(+), 6 deletions(-)
diff --git a/drivers/net/dsa/qca/qca8k-8xxx.c b/drivers/net/dsa/qca/qca8k-8xxx.c
index bc77dd45b6..01834e16a2 100644
--- a/drivers/net/dsa/qca/qca8k-8xxx.c
+++ b/drivers/net/dsa/qca/qca8k-8xxx.c
@@ -170,6 +170,7 @@ static void qca8k_rw_reg_ack_handler(struct dsa_switch *ds, struct sk_buff *skb)
struct qca8k_mgmt_eth_data *mgmt_eth_data;
struct qca8k_priv *priv = ds->priv;
struct qca_mgmt_ethhdr *mgmt_ethhdr;
+ int data_len = 0;
u32 command;
u8 len, cmd;
int i;
@@ -190,6 +191,17 @@ static void qca8k_rw_reg_ack_handler(struct dsa_switch *ds, struct sk_buff *skb)
/* We can ignore odd value, we always round up them in the alloc function. */
len *= sizeof(u16);
+ if (cmd == MDIO_READ && len > QCA_HDR_MGMT_DATA1_LEN)
+ data_len = min_t(int, QCA_HDR_MGMT_DATA2_LEN,
+ len - QCA_HDR_MGMT_DATA1_LEN);
+
+ /* The tagger made only the tag linear. Leave a frame that is too
+ * short for the data it announces unacknowledged: the read fails
+ * and the caller falls back to MDIO.
+ */
+ if (data_len && !pskb_may_pull(skb, data_len))
+ goto complete;
+
/* Make sure the seq match the requested packet */
if (get_unaligned_le32(&mgmt_ethhdr->seq) == mgmt_eth_data->seq)
mgmt_eth_data->ack = true;
@@ -199,13 +211,11 @@ static void qca8k_rw_reg_ack_handler(struct dsa_switch *ds, struct sk_buff *skb)
*val = get_unaligned_le32(&mgmt_ethhdr->mdio_data);
- /* Get the rest of the 12 byte of data.
- * The read/write function will extract the requested data.
+ /* Get the rest of the data.
+ * The read function extracts what it asked for.
*/
- if (len > QCA_HDR_MGMT_DATA1_LEN) {
+ if (data_len) {
__le32 *data2 = (__le32 *)skb->data;
- int data_len = min_t(int, QCA_HDR_MGMT_DATA2_LEN,
- len - QCA_HDR_MGMT_DATA1_LEN);
val++;
@@ -217,6 +227,7 @@ static void qca8k_rw_reg_ack_handler(struct dsa_switch *ds, struct sk_buff *skb)
}
}
+complete:
complete(&mgmt_eth_data->rw_done);
}
diff --git a/drivers/net/dsa/qca/qca8k.h b/drivers/net/dsa/qca/qca8k.h
index 79754755f1..b7aa0d832e 100644
--- a/drivers/net/dsa/qca/qca8k.h
+++ b/drivers/net/dsa/qca/qca8k.h
@@ -396,7 +396,8 @@ struct qca8k_mgmt_eth_data {
struct mutex mutex; /* Enforce one mdio read/write at time */
bool ack;
u32 seq;
- u32 data[4];
+ /* The data a management frame can carry */
+ u32 data[(QCA_HDR_MGMT_DATA1_LEN + QCA_HDR_MGMT_DATA2_LEN) / sizeof(u32)];
};
struct qca8k_mib_eth_data {
--
2.43.0
prev parent reply other threads:[~2026-11-04 21:08 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-04 21:07 [PATCH net-next v2 0/4] net: dsa: qca8k: fix the MIB autocast and management frame handlers Stanislaw Pal
2026-11-04 21:07 ` [PATCH net-next v2 1/4] net: dsa: qca8k: read each register into its own word over MDIO Stanislaw Pal
2026-11-07 3:10 ` Alexey Immoreev
2026-11-07 9:27 ` Stanislaw Pal
2026-11-04 21:07 ` [PATCH net-next v2 2/4] net: dsa: qca8k: drop MIB autocast frames once the request is over Stanislaw Pal
2026-11-04 21:07 ` [PATCH net-next v2 3/4] net: dsa: qca8k: check the length of MIB autocast frames Stanislaw Pal
2026-11-04 21:07 ` Stanislaw Pal [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=20261104210757.467964-5-kuncy7@gmail.com \
--to=kuncy7@gmail.com \
--cc=andrew@lunn.ch \
--cc=ansuelsmth@gmail.com \
--cc=davem@davemloft.net \
--cc=edumazet@kernel.org \
--cc=kuba@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=netdev@vger.kernel.org \
--cc=olteanv@gmail.com \
--cc=pabeni@redhat.com \
--cc=yongzhao.derek@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 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.