Hello U-Boot maintainers,

I found an overlap between the MPC8xx serial receive buffer and the SPI buffer 
descriptors in DPRAM.

Tested version
==============

U-Boot v2026.10-rc5
Commit: a06e89ab05eaa2b8344d521319399333cd760ae5

Relevant configuration
======================

CONFIG_MPC8xx=y
CONFIG_MPC8XX_CONS=y
CONFIG_SYS_SMC_RXBUFLEN=64
CONFIG_SPI=y
CONFIG_DM_SPI=y
CONFIG_MPC8XX_SPI=y

Summary
=======

The MPC8xx serial driver places struct serialbuffer at the fixed DPRAM address
0x800. The size of its rxbuf member is controlled by
CONFIG_SYS_SMC_RXBUFLEN, which has no Kconfig range limiting it against other
fixed DPRAM allocations.

The MPC8xx SPI driver places its receive and transmit buffer descriptors at
the fixed addresses 0x840 and 0x848.

With CONFIG_SYS_SMC_RXBUFLEN=64, the serial receive buffer occupies addresses
0x814 through 0x853. This overlaps the complete 16-byte SPI descriptor region
at 0x840 through 0x84f. Receiving 64 bytes through the SMC serial interface can
therefore cause CPM DMA to overwrite both SPI descriptors.

Technical details
=================

drivers/serial/serial_mpc8xx.c defines the serial DPRAM object as follows:

    struct serialbuffer {
        cbd_t rxbd;
        cbd_t txbd;
        uint rxindex;
        uchar rxbuf[CONFIG_SYS_SMC_RXBUFLEN];
        uchar txbuf;
    };

The object starts at a fixed DPRAM address:

    #define CPM_SERIAL_BASE 0x0800

    rtx = (struct serialbuffer __iomem *)
          &cp->cp_dpmem[CPM_SERIAL_BASE];

cbd_t is 8 bytes, so rxbuf begins at offset 20 in struct serialbuffer. The
serial driver configures this address as the receive DMA buffer and uses the
Kconfig value as the maximum receive length:

    out_be32(&rtx->rxbd.cbd_bufaddr, (__force uint)&rtx->rxbuf);
    out_be16(&up->smc_mrblr, CONFIG_SYS_SMC_RXBUFLEN);

The SPI driver uses the following fixed addresses in the same DPRAM:

    #define CPM_SPI_BASE     0x0840
    #define CPM_SPI_BASE_RX  CPM_SPI_BASE
    #define CPM_SPI_BASE_TX  (CPM_SPI_BASE + sizeof(cbd_t))

    rbdf = (cbd_t __iomem *)&cp->cp_dpmem[CPM_SPI_BASE_RX];
    tbdf = (cbd_t __iomem *)&cp->cp_dpmem[CPM_SPI_BASE_TX];

With CONFIG_SYS_SMC_RXBUFLEN=64, the resulting ranges are:

    serialbuffer base       = 0x800
    serial rxbuf offset     = 0x14
    serial rxbuf start      = 0x814
    serial rxbuf end        = 0x853

    SPI RX descriptor       = 0x840 .. 0x847
    SPI TX descriptor       = 0x848 .. 0x84f

    overlapping range       = 0x840 .. 0x84f
    overlap size            = 16 bytes

The serial receive buffer reaches the SPI region whenever
CONFIG_SYS_SMC_RXBUFLEN is greater than 44. The Kconfig option currently has
no range constraint for this boundary.

Reproduction
============

1. Configure U-Boot from CMPC885_defconfig.
2. Set the following options:

       CONFIG_SYS_SMC_RXBUFLEN=64
       CONFIG_MPC8XX_SPI=y

3. Initialize the serial and SPI drivers.
4. Write identifiable initial values to the SPI RX and TX descriptors.
5. Receive 64 bytes through the SMC serial RX path.
6. Inspect DPRAM addresses 0x840 through 0x84f.

A reproduction using U-Boot's structure definitions and fixed DPRAM addresses
confirmed that all 16 bytes of the two SPI descriptors change after the serial
RX write:

    serial_rx=[0x814,0x853]
    spi_rx_descriptor=[0x840,0x847]
    spi_tx_descriptor=[0x848,0x84f]
    overlap=16

    SPI descriptors overwritten by configured serial RX buffer

Impact
======

Input received through the serial console can overwrite the following fields
in both SPI descriptors:

    cbd_sc
    cbd_datlen
    cbd_bufaddr

This can cause SPI transaction failures, timeouts, a U-Boot crash, or invalid
memory accesses during subsequent SPI processing. Corruption of cbd_bufaddr
may also affect the memory address used by SPI DMA.

The confirmed result is the 16-byte DPRAM overlap and descriptor overwrite.
I have not yet reproduced an end-to-end crash or arbitrary memory corruption
on physical MPC8xx hardware.

Regards,
Jaeyeong Lee

Reply via email to