[BUG] drivers/net/ftmac100.c: device-reported RX frame length drives an unbounded `memcpy` into the fixed packet buffer (OOB write)

Cerrado Apto para principiantes
#21,111 0 comentarios 0 reacciones 0 asignados Ver en GitHub

Los mantenedores suelen responder en 1 día

Ya se ha fusionado un pull request relacionado.

  • #21304 de @Swatantra-66 — fusionado

Evaluación

Dificultad
2/5
Tiempo estimado
1-3 horas
Aptitud para principiantes
70/100
Tipo de issue
Error
Claridad
Bien especificado
Estado de actividad
Activo
Stack tecnológico
c

Línea de trabajo

Empieza con ftmac100_receive() en drivers/net/ftmac100.c y luego revisa la máscara de longitud RX en include/nuttx/net/ftmac100.h y el tamaño del búfer de paquetes en el controlador. Confirma la longitud máxima aceptada frente a la capacidad del destino y compara la ruta de rechazo en drivers/net/encx24j600.c. El trabajo estará terminado cuando las tramas demasiado grandes o no válidas se descarten de forma segura y se superen las comprobaciones pertinentes del controlador.

Escrito por el modelo de indexación a partir del texto del issue.

Descripción

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

In drivers/net/ftmac100.c (Faraday FTMAC100 10/100 MAC) the RX path memcpys the DMA-descriptor
frame length into the fixed packet buffer with no clamp against buffer capacity. The bound is
absent in all build configurations (not assert-gated). This is an out-of-bounds write of up
to ~1455 bytes of wire-controlled data past the per-interface packet buffer, into adjacent interface
buffers / BSS. The attacker is a link peer (or a malfunctioning/compromised MAC) that reports an
oversized RX frame length in the DMA descriptor status word.

ftmac100_receive() reads the RX frame length directly from the DMA descriptor and memcpys
that many bytes into the device packet buffer with no clamp against the buffer capacity:

/* drivers/net/ftmac100.c */
624   len  = FTMAC100_RXDES0_RFL(rxdes->rxdes0);   /* RX Frame Length from DMA descriptor */
625   data = (FAR uint8_t *)rxdes->rxdes2;         /* DMA RX buffer pointer */
...
635   memcpy(priv->ft_dev.d_buf, data, len);       /* no clamp vs d_buf capacity */
636   priv->ft_dev.d_len = len;

FTMAC100_RXDES0_RFL (include/nuttx/net/ftmac100.h:118) is ((des) & 0x7ff), i.e. a value
of 0..2047 taken verbatim from the descriptor status word the MAC/DMA writes.

The destination priv->ft_dev.d_buf is g_pktbuf[intf] (ftmac100.c:180,1353), sized
PKTBUF_SIZE = MAX_NETDEV_PKTSIZE + CONFIG_NET_GUARDSIZE. With the default
CONFIG_NET_ETH_PKTSIZE = 590 (include/nuttx/net/netconfig.h:207) the buffer is ~592 bytes,
so a reported length up to 2047 overflows it by up to ~1455 bytes.

There is no length check at all — not even a DEBUGASSERT — between the RFL read at :624
and the memcpy at :635. ftmac100_receive() runs off the RX interrupt work path for every
received frame; the length field is attacker/wire controlled and no userspace open()/read() is
required. Gated by CONFIG_FTMAC100 (e.g. QEMU/moxart, k210-class targets).

Why this is a bug (smoking gun): a sibling MAC driver rejects the oversized length.
drivers/net/encx24j600.c:1620-1628 reads the hardware RX status-vector length and drops the
frame when it is out of range:

else if (pktlen > (CONFIG_NET_ETH_PKTSIZE + 4) || pktlen <= (ETH_HDRLEN + 4))
  { nerr("Bad packet size dropped"); enc_rxrmpkt(...); NETDEV_RXERRORS(...); }

ftmac100 omits this equivalent bounds check on the same kind of device-reported RX length.

Note the precondition is modest: the destination is only ~592 bytes (default config) while the RFL
field allows up to 2047 and the DMA RX region is 2044 bytes, so any ordinary receivable frame larger
than ~592 bytes
(a normal ~1000-byte Ethernet frame) already overflows via the unchecked memcpy —
no forged 2000-byte giant frame is required. The ~1455-byte figure is just the worst case
(2047 - 592).

Steps:

  1. Build with CONFIG_FTMAC100 and bring up the interface.
  2. From a link peer (or a malfunctioning/compromised MAC) deliver/report an RX frame larger than the
    ~592-byte d_buf — an ordinary ~1000-byte Ethernet frame suffices; up to 2047 is possible.
  3. ftmac100_receive() memcpys that many bytes into the ~592-byte g_pktbuf, overflowing it.

An AddressSanitizer build with the RFL mask (0x7ff), the 592-byte g_pktbuf, and an unclamped
memcpy of a normal oversize frame (e.g. len=1000) reports:

heap-buffer-overflow WRITE past the 592-byte region

Suggested fix: before the memcpy, reject or clamp the reported length, mirroring the
encx24j600 check:

if (len > CONFIG_NET_ETH_PKTSIZE || len <= ETH_HDRLEN)
  {
    NETDEV_RXERRORS(&priv->ft_dev);
    /* drop the frame, advance the descriptor */
  }
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.
Lenguaje dominante
C
Estrellas
4.1k
Forks
1.7k
Merge medio
1 d 3 h
PR fusionados (30 d)
786

Preparar el entorno

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Más de apache/nuttx

Todos los issues de apache/nuttx

Issues similares

Más issues de C

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.