From: Ana Bobillo <anabobillo3@gmail.com>
To: Marek Vasut <marek.vasut+usb@mailbox.org>
Cc: Tom Rini <trini@konsulko.com>, Simon Glass <sjg@chromium.org>,
Jonas Karlman <jonas@kwiboo.se>,
u-boot@lists.u-boot-project.org
Subject: [PATCH RESEND 3/4] usb: eth: lan7x: Account for the whole rx command header
Date: Thu, 29 Oct 2026 06:06:59 +0000 [thread overview]
Message-ID: <4e514187-efe2-47ba-8a86-de4ba3c25cd1@gmail.com> (raw)
In-Reply-To: <f9afa215-645f-400f-8743-eaeca3f6a2f5@gmail.com>
From: Ana Bobillo <anabobillo3@gmail.com>
lan7x_eth_recv() returns the frame that follows rx command A, B and C,
10 bytes into the transfer, but checks only that the transfer holds
command A and that the frame fits in what follows command A. A transfer
of 4 to 9 bytes, or a frame length up to 6 bytes longer than what
follows the header, hands the network stack a frame that runs past the
received data.
On LAN75xx, command A and B are followed by 2 bytes of padding rather
than command C, and the length in command A counts them, as Linux
smsc75xx_rx_fixup() has it: the frame handed up was 2 bytes longer than
the one received, running past the transfer. Take the padding out of the
length there, so that the frame can be bounded by what follows the
header on both.
lan7x_free_pkt() also steps over only 4 bytes of header, so the tail of
a frame is parsed as the header of another. Step over the 10 bytes of
header, the frame and the padding that aligns the next header to
4 bytes, as Linux lan78xx_rx() and smsc75xx_rx_fixup() do.
Signed-off-by: Ana Bobillo <anabobillo3@gmail.com>
---
drivers/usb/eth/lan7x.c | 31 ++++++++++++++++++++-----------
drivers/usb/eth/lan7x.h | 4 ++++
2 files changed, 24 insertions(+), 11 deletions(-)
diff --git a/drivers/usb/eth/lan7x.c b/drivers/usb/eth/lan7x.c
index 0a283619ae5..14c3ace4cc9 100644
--- a/drivers/usb/eth/lan7x.c
+++ b/drivers/usb/eth/lan7x.c
@@ -446,8 +446,8 @@ int lan7x_eth_recv(struct udevice *dev, int flags, uchar **packetp)
* 1st 4 bytes contain the length of the actual data plus error info.
* Extract data length.
*/
- if (len < sizeof(packet_len)) {
- debug("Rx: incomplete packet length\n");
+ if (len < RX_CMD_LEN) {
+ debug("Rx: incomplete packet header\n");
goto err;
}
memcpy(&rx_cmd_a, ptr, sizeof(rx_cmd_a));
@@ -458,18 +458,26 @@ int lan7x_eth_recv(struct udevice *dev, int flags, uchar **packetp)
}
packet_len = (u16) (rx_cmd_a & RX_CMD_A_LEN_MASK);
- if (packet_len > len - sizeof(packet_len)) {
- debug("Rx: too large packet: %d\n", packet_len);
- goto err;
- }
-
/*
* For LAN7x, the length in command A does not
* include command A, B, and C length.
- * So use it as is.
+ * On LAN75xx, command A and B are followed by 2 bytes of
+ * padding instead, which the length does include.
*/
+ if (priv->chipid == ID_REV_CHIP_ID_7500) {
+ if (packet_len < RX_LAN75XX_PADDING) {
+ debug("Rx: too small packet: %d\n", packet_len);
+ goto err;
+ }
+ packet_len -= RX_LAN75XX_PADDING;
+ }
+
+ if (packet_len > len - RX_CMD_LEN) {
+ debug("Rx: too large packet: %d\n", packet_len);
+ goto err;
+ }
- *packetp = ptr + 10;
+ *packetp = ptr + RX_CMD_LEN;
return packet_len;
err:
@@ -481,8 +489,9 @@ int lan7x_free_pkt(struct udevice *dev, uchar *packet, int packet_len)
{
struct lan7x_private *priv = dev_get_priv(dev);
- packet_len = ALIGN(packet_len, 4);
- usb_ether_advance_rxbuf(&priv->ueth, sizeof(u32) + packet_len);
+ /* Skip command A, B and C, the frame and its padding to 4 bytes */
+ packet_len = ALIGN(RX_CMD_LEN + packet_len, 4);
+ usb_ether_advance_rxbuf(&priv->ueth, packet_len);
return 0;
}
diff --git a/drivers/usb/eth/lan7x.h b/drivers/usb/eth/lan7x.h
index 9480f4f6d15..29f06c076c5 100644
--- a/drivers/usb/eth/lan7x.h
+++ b/drivers/usb/eth/lan7x.h
@@ -23,6 +23,10 @@
#define RX_CMD_A_RXE BIT(18)
#define RX_CMD_A_LEN_MASK 0x00003FFF
+/* Rx Command A, B and C (or padding) in front of each received frame */
+#define RX_CMD_LEN 10
+#define RX_LAN75XX_PADDING 2
+
/* SCSRs */
#define ID_REV 0x00
#define ID_REV_CHIP_ID_MASK 0xFFFF0000
next prev parent reply other threads:[~2026-10-29 6:07 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-29 6:06 [PATCH RESEND 0/4] usb: eth: Check rx header lengths in r8152, asix88179 and lan7x Ana Bobillo
2026-10-29 6:06 ` [PATCH RESEND 1/4] usb: eth: r8152: Check the rx descriptor fits in the transfer Ana Bobillo
2026-10-29 6:06 ` [PATCH RESEND 2/4] usb: eth: asix88179: Bound the rx packet headers and packets Ana Bobillo
2026-10-29 6:06 ` Ana Bobillo [this message]
2026-10-29 6:07 ` [PATCH RESEND 4/4] test: dm: Add tests for the USB Ethernet rx header checks Ana Bobillo
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=4e514187-efe2-47ba-8a86-de4ba3c25cd1@gmail.com \
--to=anabobillo3@gmail.com \
--cc=jonas@kwiboo.se \
--cc=marek.vasut+usb@mailbox.org \
--cc=sjg@chromium.org \
--cc=trini@konsulko.com \
--cc=u-boot@lists.u-boot-project.org \
/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.