From: "M, Krishnamoorthi" <krishnamoorthi.m@amd.com>
To: Weibin Liu <liuwb@xiaopeng.com>,
linux-spi@vger.kernel.org, broonie@kernel.org,
Raju.Rangoju@amd.com
Cc: linux-kernel@vger.kernel.org, sanju.mehta@amd.com,
stable@vger.kernel.org, Guanglei Zhu <zhugl3@xiaopeng.com>
Subject: Re: [PATCH] spi: amd: fix len==0 underflow and FIFO overflow
Date: Fri, 16 Oct 2026 16:57:06 +0530 [thread overview]
Message-ID: <6b532bcd-c36d-4b1f-b0c5-9b6b2dc85efe@amd.com> (raw)
In-Reply-To: <20261014-spi-amd-fifo-fix-v1-1-9fec9ab753e8@xiaopeng.com>
Hi,
On 10/14/2026 6:09 PM, Weibin Liu wrote:
> [You don't often get email from liuwb@xiaopeng.com. Learn why this is important at https://aka.ms/LearnAboutSenderIdentification ]
>
> amd_spi_fifo_xfer() unconditionally decrements xfer->len when a tx_buf
> is present. The SPI core does not reject zero-length transfers, so a
> transfer submitted through the SPI_IOC_MESSAGE ioctl with len == 0 and
> a tx_buf makes the u32 len wrap to 0xFFFFFFFF, and the following
> per-byte loop writes far past the FIFO window.
>
> The driver also never checks the cumulative FIFO offset against
> AMD_SPI_FIFO_SIZE. The core splits each transfer down to the
> controller's max transfer size but does not bound the total message
> length, so a message of several transfers whose total exceeds the FIFO
> overflows it with out-of-bounds MMIO writes (tx) and reads (rx).
>
> Skip zero-length transfers and reject any transfer that would run past
> the end of the FIFO window.
>
> Tested with a user-space replica of the fifo_xfer length arithmetic
> (ASAN build): a zero-length transfer with tx_buf makes len-- wrap to
> 0xffffffff, and skipping zero-length transfers avoids the wrap. No AMD
> SPI hardware was available, so the FIFO bound check was verified by
> inspection against AMD_SPI_FIFO_SIZE.
>
> Fixes: bbb336f39efc ("spi: spi-amd: Add AMD SPI controller driver support")
> Cc: stable@vger.kernel.org # 5.8+
> Reviewed-by: Guanglei Zhu <zhugl3@xiaopeng.com>
> Signed-off-by: Weibin Liu <liuwb@xiaopeng.com>
> ---
> drivers/spi/spi-amd.c | 17 +++++++++++++++++
> 1 file changed, 17 insertions(+)
>
> diff --git a/drivers/spi/spi-amd.c b/drivers/spi/spi-amd.c
> index 71a6e5c475b0..ddf89e5353c5 100644
> --- a/drivers/spi/spi-amd.c
> +++ b/drivers/spi/spi-amd.c
> @@ -322,11 +322,22 @@ static inline int amd_spi_fifo_xfer(struct amd_spi *amd_spi,
>
> list_for_each_entry(xfer, &message->transfers,
> transfer_list) {
> + /* Skip zero-length transfers to avoid len underflow below */
> + if (!xfer->len)
> + continue;
> +
> if (xfer->speed_hz)
> amd_set_spi_freq(amd_spi, xfer->speed_hz);
> else
> amd_set_spi_freq(amd_spi, spi->max_speed_hz);
>
> + /* Reject transfers that would overflow the FIFO window */
> + if (fifo_pos + xfer->len >
> + AMD_SPI_FIFO_BASE + AMD_SPI_FIFO_SIZE) {
> + message->status = -EMSGSIZE;
> + goto fin_msg;
> + }
> +
> if (xfer->tx_buf) {
> buf = (u8 *)xfer->tx_buf;
> if (!tx_len) {
> @@ -369,6 +380,12 @@ static inline int amd_spi_fifo_xfer(struct amd_spi *amd_spi,
>
> list_for_each_entry(xfer, &message->transfers, transfer_list)
> if (xfer->rx_buf) {
> + /* Reject transfers that would overflow the FIFO window */
> + if (fifo_pos + xfer->len >
> + AMD_SPI_FIFO_BASE + AMD_SPI_FIFO_SIZE) {
> + message->status = -EMSGSIZE;
> + goto fin_msg;
> + }
> buf = (u8 *)xfer->rx_buf;
> /* Read data from FIFO to receive buffer */
> for (i = 0; i < xfer->len; i++)
>
> ---
Thanks for the fix. The zero-length skip and the overflow bound are both
correct, but the FIFO check can be done more simply and, more
importantly, before the command is issued.
fifo_pos only advances in the tx branch, so this form can't track the
cumulative rx length in the first loop. That's why you need the second
copy in the drain loop - but by then amd_spi_execute_opcode() has
already run, so an oversized message still drives one SPI transaction
before being rejected.
Please use tx_len + rx_len against AMD_SPI_FIFO_SIZE and check it in the
first loop only, so the whole message is validated before execute and
the drain-loop check can be dropped:
if (xfer->tx_buf) {
...
tx_len += xfer->len;
if (tx_len + rx_len > AMD_SPI_FIFO_SIZE) {
message->status = -EMSGSIZE;
goto fin_msg;
}
...
}
...
/* Store no. of bytes to be received from FIFO */
if (xfer->rx_buf) {
rx_len += xfer->len;
if (tx_len + rx_len > AMD_SPI_FIFO_SIZE) {
message->status = -EMSGSIZE;
goto fin_msg;
}
}
Thanks,
Krishna
> base-commit: 24a19b953e2a3d0ea5a8c4951a0ab8f32720c907
> change-id: 20261014-spi-amd-fifo-fix-37ac4ef05bf6
>
> Best regards,
> --
> Weibin Liu <liuwb@xiaopeng.com>
>
prev parent reply other threads:[~2026-10-16 11:27 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-14 12:39 Weibin Liu
2026-10-15 22:25 ` Mark Brown
2026-10-16 12:16 ` M, Krishnamoorthi
2026-10-16 11:27 ` M, Krishnamoorthi [this message]
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=6b532bcd-c36d-4b1f-b0c5-9b6b2dc85efe@amd.com \
--to=krishnamoorthi.m@amd.com \
--cc=Raju.Rangoju@amd.com \
--cc=broonie@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-spi@vger.kernel.org \
--cc=liuwb@xiaopeng.com \
--cc=sanju.mehta@amd.com \
--cc=stable@vger.kernel.org \
--cc=zhugl3@xiaopeng.com \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®