[PATCH v2 5/6] firmware: samsung: acpm: Fix out-of-bounds read and infinite loop in RX path

From: Tudor Ambarus

Date: Mon Apr 27 2026 - 11:06:08 EST


Sashiko identified these bugs in [1].

The ACPM driver reads the rx_front and rx_rear pointers directly from
SRAM and uses them to calculate SRAM offsets and loop termination
conditions.

If a firmware bug writes a value greater than or equal to the queue
length (achan->qlen) at those addresses, two failures occur:

1. Out-of-bounds read: The rear pointer ('i') is used to calculate the
MMIO address before the modulo operation is applied, leading to an
immediate out-of-bounds memory access.
2. Infinite loop: The loop iterates using 'i = (i + 1) % achan->qlen'.
Because 'i' is mathematically capped below qlen, if 'rx_front' is
greater than or equal to qlen, 'i' will never equal 'rx_front'.
The CPU will spin forever, holding the rx_lock and deadlocking the
polling thread.

Protect the kernel by strictly validating the MMIO queue offsets
immediately after reading them.

Cc: stable@xxxxxxxxxxxxxxx
Fixes: a88927b534ba ("firmware: add Exynos ACPM protocol driver")
Closes: https://sashiko.dev/#/patchset/20260420-acpm-tmu-v3-0-3dc8e93f0b26%40linaro.org [1]
Signed-off-by: Tudor Ambarus <tudor.ambarus@xxxxxxxxxx>
---
drivers/firmware/samsung/exynos-acpm.c | 7 +++++++
1 file changed, 7 insertions(+)

diff --git a/drivers/firmware/samsung/exynos-acpm.c b/drivers/firmware/samsung/exynos-acpm.c
index c9aa79c2faa4..43658cc1347a 100644
--- a/drivers/firmware/samsung/exynos-acpm.c
+++ b/drivers/firmware/samsung/exynos-acpm.c
@@ -230,6 +230,13 @@ static int acpm_get_rx(struct acpm_chan *achan, const struct acpm_xfer *xfer)
rx_front = readl(achan->rx.front);
i = readl(achan->rx.rear);

+ if (rx_front >= achan->qlen || i >= achan->qlen) {
+ dev_err(achan->acpm->dev,
+ "Invalid RX queue pointers from firmware: front=%u rear=%u qlen=%u\n",
+ rx_front, i, achan->qlen);
+ return -EIO;
+ }
+
tx_seqnum = FIELD_GET(ACPM_PROTOCOL_SEQNUM, xfer->txd[0]);

if (i == rx_front) {

--
2.54.0.rc2.544.gc7ae2d5bb8-goog