Hacktoberfest 2026: los issues que los mantenedores marcaron para octubre, abiertos y aptos para principiantes. Explorar issues de Hacktoberfest

[Bug] OOB write in OpenAMP virtual UART RX ring buffer on stm32mp157a-st-ev1

Abierto
#11,299 2 comentarios 0 reacciones 1 asignado Ver en GitHub

Los mantenedores suelen responder en 1 día

@manyangshen ya está trabajando en esto.

Desde el 22/9/2026.

  • #11825 de @manyangshen — abierto

Evaluación

Dificultad
4/5
Tiempo estimado
3-5 días
Aptitud para principiantes
48/100
Tipo de issue
Error
Claridad
Bastante claro
Estado de actividad
Tranquilo
Stack tecnológico
c

Línea de trabajo

Comienza en el BSP de STM32MP157A-ST-EV1, en drv_openamp.c, en VIRT_UART0_RxCpltCallback() y _read(), y después revisa cómo VIRT_UART_read_cb() pasa los datos de rpmsg al callback de RX. Reproduce el problema con escrituras controladas en /dev/ttyRPMSG0, incluida una escritura de 255 bytes seguida de una escritura de 2 bytes. Se considera terminado cuando el anillo RX no puede escribir más allá de su búfer, la condición de wrap de lectura es segura y la reproducción ya no causa corrupción ni un fault.

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

Descripción

in progress
RT-Thread Version

master at commit fe548e1505

Hardware Type/Architectures

STM32MP157A-ST-EV1 BSP with BSP_USING_OPENAMP enabled.

Develop Toolchain

GCC

Describe the bug

There is a reachable memory-safety issue in the OpenAMP virtual UART receive path of the stm32mp157a-st-ev1 BSP.

VIRT_UART_read_cb() receives rpmsg data from the OpenAMP peer and forwards the externally controlled payload pointer and length into the registered RX callback:

huart->pRxBuffPtr = data;
huart->RxXferSize = len;
huart->RxCpltCallback(huart);

In this BSP, the registered callback is VIRT_UART0_RxCpltCallback() in drv_openamp.c. That callback copies the received payload into a 256-byte ring buffer, but the bounds logic is incorrect:

  1. It checks only if (count < size) once before the copy loop
  2. It does not verify that count + rx_size <= size
  3. It does not wrap offset during the copy loop

As a result, if the ring buffer already contains 255 bytes and a new 2-byte message arrives, the callback writes:

  • The first byte to buf[255]
  • The second byte to buf[256]

This is an out-of-bounds write.

The bug is not limited to the minimal 2-byte case. A larger second message increases the overwrite extent further because the loop continues writing past the end of the 256-byte receive buffer.

In addition, the read path in _read() also contains a wrap bug: it uses if (offset > rbsize) instead of if (offset >= rbsize). Once the ring-buffer state becomes invalid, this can also cause an out-of-bounds read on subsequent reads.

This issue is reachable in the current BSP integration. The input channel is concrete:

  • The BSP is configured with LINUX_RPROC_MASTER
  • CM4 initializes OpenAMP as RPMSG_REMOTE
  • The virtual UART endpoint name is rpmsg-tty-channel
  • The repository already includes tools/rt-thread-shell.py, which writes to /dev/ttyRPMSG0

Therefore, an attacker who can control the OpenAMP peer, or who can send controlled input through the CA7/Linux side into /dev/ttyRPMSG0 or the corresponding rpmsg endpoint, can trigger this bug.


Fix Suggestion

A safe fix should address both the RX callback and the read path.

Suggested changes:

  1. In VIRT_UART0_RxCpltCallback(), compute available space before copying:
    • available = size - count
    • If available == 0, drop the message or return an error
  2. Clamp rx_size to the available space before entering the loop
  3. Wrap offset on each iteration, not only once before the loop
  4. Ensure device->serial.rbuf_count never exceeds device->serial.rbuf_size
  5. In _read(), change the wrap condition from if (offset > rbsize) to if (offset >= rbsize)
  6. Prefer using a common ring-buffer helper instead of open-coded wrap logic

Pseudo-fix direction:

available = size - count;
rx_size = MIN(rx_size, available);

for (i = 0; i < rx_size; i++)
{
    if (offset >= size)
        offset = 0;
    buf[offset++] = huart->pRxBuffPtr[i];
    count++;
}

Exploitation Idea

Precondition: the attacker can control the OpenAMP peer, i.e. the CA7/Linux side can send data to /dev/ttyRPMSG0 or the corresponding rpmsg endpoint.

Minimal PoC idea:

  1. Send 255 bytes from the Linux side to make the CM4-side receive ring buffer nearly full.
  2. Send one more message with length 2.
  3. The second message triggers the out-of-bounds write in VIRT_UART0_RxCpltCallback().

High-level example from the Linux side:

  • Open /dev/ttyRPMSG0
  • Write 255 controlled bytes
  • Then write 2 more controlled bytes

A simple proof-of-concept can be implemented with a short userspace program or script that performs two writes in sequence.

For a more stable reproduction:

  • Make sure the CM4 side is not draining the openamp receive buffer too quickly
  • For example, avoid using openamp as the active console during reproduction, or pause the consumer if applicable

Observation ideas:

  • Monitor for CM4 fault / crash / unexpected behavior
  • Inspect adjacent memory corruption effects after the second write
  • After corrupting the ring state, trigger reads from the openamp device to exercise the buggy _read() wrap logic and observe potential OOB read behavior
Other additional context

No response

Lenguaje dominante
C
Estrellas
12.3k
Forks
5.5k
Merge medio
4 d 12 h
PR fusionados (30 d)
32

Preparar el entorno

Abrir en Codespaces

Inicia el contenedor de desarrollo del proyecto en tu navegador, con tu propia cuenta de GitHub.

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 RT-Thread/rt-thread

Todos los issues de RT-Thread/rt-thread

Issues similares

Más issues de C

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.