Hacktoberfest 2026: le issue che i maintainer hanno segnato per ottobre, aperte e adatte ai principianti. Sfoglia le issue Hacktoberfest

[BUG] drivers/net/lan9250.c: `.bss`/global `pktbuf` overflow in `lan9250_recv_buffer` — RX-status packet length bounded only by `DEBUGASSERT` (SPI path only)

Aperta Adatta ai principianti
#21,112 1 commento 0 reazioni 0 assegnatari Vedi su GitHub

I maintainer di solito rispondono entro 1 giorno

Nessuno ha ancora preso questa issue.

Valutazione

Difficoltà
2/5
Tempo stimato
1-3 ore
Idoneità per principianti
68/100
Tipo di issue
Bug
Chiarezza
Specificata chiaramente
Stato di attività
Attiva
Stack tecnologico
c
Ambito
embedded-iot

Direzione di ricerca

Inizia in drivers/net/lan9250.c, da lan9250_receive() e lan9250_recv_buffer(). Poi controlla come viene dimensionato pktbuf e come i percorsi SPI e QSPI/SQI copiano i dati. Aggiungi un controllo della capacità sempre attivo prima di ogni copia e scarta i frame troppo grandi. Il lavoro è completo quando le lunghezze ricevute non possono scrivere oltre pktbuf su nessuno dei due percorsi.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

Arch: all Area: Drivers OS: Linux Type: Bug
Description / Steps to reproduce the issue

In drivers/net/lan9250.c (LAN9250 Ethernet driver over SPI/QSPI) the received frame length taken
from the RX Status FIFO is used as a copy length into priv->pktbuf, bounded on the SPI path only
by an assert that compiles to nothing in the default build, and on the QSPI/SQI path by no capacity
check at all
. priv is a static global object, so this is an out-of-bounds write into .bss
that first clobbers the structure members immediately following pktbuf (a watchdog timer and several
work structures) and then adjacent globals. The attacker is a peer on the same L2 network sending an
oversized frame, or a malicious/faulty LAN9250 PHY.

lan9250_receive() takes the received frame length from the LAN9250 RX Status FIFO register and
passes it as the copy length, with only a non-zero check:

/* drivers/net/lan9250.c:1747-1748  (lan9250_receive) */
regval = lan9250_get_reg(priv, LAN9250_RXSFR);        /* RX Status FIFO register */
pktlen = (regval & RXSFF_PL_M) >> RXSFF_PL_S;         /* 14-bit length field, 0..16383 */
if (pktlen)                                           /* only a non-zero check */
    lan9250_recv_buffer(priv, priv->dev.d_buf, pktlen);  /* buflen = pktlen */

The copy then runs into priv->pktbuf. On the SPI path the length is bounded only by a
DEBUGASSERT; on the QSPI/SQI path there is no capacity check:

/* drivers/net/lan9250.c:853 (inside #ifdef CONFIG_LAN9250_SPI) */
DEBUGASSERT(buflen <= sizeof(priv->pktbuf));          /* SPI path: default-off assert */
...
SPI_RECVBLOCK(priv->spi, buffer, buflen);             /* buffer = priv->dev.d_buf = priv->pktbuf */

/* drivers/net/lan9250.c:881-899 (#else — QSPI/SQI path) */
meminfo.buflen = buflen;                               /* no capacity check at all */
QSPI_MEMORY(priv->qspi, &meminfo);

priv->pktbuf is uint32_t pktbuf[LAN9250_PKTBUF_SIZE / 4] (:212), with
LAN9250_PKTBUF_SIZE = LAN9250_ALIGN(MAX_NETDEV_PKTSIZE + CONFIG_NET_GUARDSIZE + 4) (:142). In the
default IPv4/Ethernet config (CONFIG_NET_ETH_PKTSIZE = 590, CONFIG_NET_GUARDSIZE = 2) that is
ALIGN(596) = 596 bytes — about one max Ethernet frame. Any ordinary frame larger than ~596 bytes
(a normal 1514/1518-byte Ethernet frame already qualifies) therefore overflows it. pktlen is a
14-bit RX-status register field (max 16383); that width is the hardware status-field size, not a
demonstration that a peer can inject a 16 KB frame — the practically reachable and sufficient case is
simply "frame > ~596 bytes".

Memory class: the driver state is a static global, not a heap allocation:

/* drivers/net/lan9250.c:230 */
static struct lan9250_driver_s g_lan9250;
/* :2440 / :2512 */  priv = &g_lan9250;   /* no kmm_malloc/kmm_zalloc of the driver state */

pktbuf (:212) is immediately followed in the struct by txtout_timer (struct wdog_s),
txtout_work / txpoll_work / irq_work (struct work_s), and dev (:214-224). So the overflow
is a .bss/global-buffer overflow that corrupts those sibling members (watchdog + work queue
state) first, then neighbouring .bss objects — it is not a heap overflow.

Configuration dimension:

  • SPI build, CONFIG_DEBUG_ASSERTIONS = n (default): the guard is compiled out → overflow.
  • SPI build, CONFIG_DEBUG_ASSERTIONS = y: the assert fires → controlled panic (DoS), no overflow.
  • QSPI/SQI build (#else path): there is no capacity check in any configuration, so enabling
    assertions does not prevent the overflow on QSPI/SQI targets.

Why this is a bug: the length is a parameter at the sink (lan9250_recv_buffer)
that originates in the caller (lan9250_receive), and the only guard anywhere on the SPI path is the
default-off DEBUGASSERT at :853 (and nothing at all on the QSPI path). The caller's if (pktlen)
check is non-zero-only, with no upper bound against MAX_NETDEV_PKTSIZE before handing the
device-reported length to the copy.

Steps:

  1. Build the LAN9250 driver (SPI with default CONFIG_DEBUG_ASSERTIONS unset, or any QSPI/SQI build).
  2. A peer on the same L2 network sends a frame larger than ~596 bytes (an ordinary full-size Ethernet
    frame suffices), or a malicious/faulty LAN9250 PHY reports an oversized RX-status length.
  3. The copy writes pktlen bytes into the 596-byte g_lan9250.pktbuf, overflowing into the adjacent
    watchdog/work members and .bss.

An AddressSanitizer build of the copy with the real buffer sizing (as a 596-byte global region)
reports a global-buffer-overflow WRITE.

Suggested fix: add an always-compiled check before lan9250_recv_buffer, and/or replace the
DEBUGASSERT, and add the equivalent check on the QSPI/SQI path:

if (pktlen > MAX_NETDEV_PKTSIZE)
  {
    /* drop oversized frame */
    return;
  }

and in lan9250_recv_buffer replace the SPI DEBUGASSERT with if (buflen > sizeof(priv->pktbuf)) return;
and add the same guard before the QSPI QSPI_MEMORY transfer.

On which OS does this issue occur?

[OS: Linux]

What is the version of your OS?

ubuntu 22

NuttX Version

master

Issue Architecture

[Arch: all]

Issue Area

[Area: Drivers]

Host information

No response

Verification
  • I have verified before submitting the report.
Lingua principale
C
Stelle
4.1k
Fork
1.7k
Merge medio
1g 10h
PR unite (30g)
649

Preparare l'ambiente

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di apache/nuttx

Tutte le issue di apache/nuttx

Issue simili

Altre issue su C

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.