From: Sasha Levin <sashal@kernel.org>
To: stable@vger.kernel.org
Cc: Tudor Ambarus <tudor.ambarus@linaro.org>,
Krzysztof Kozlowski <krzk@kernel.org>,
Sasha Levin <sashal@kernel.org>
Subject: [PATCH 7.0.y 5/5] firmware: samsung: acpm: Fix missing LKMM barriers in sequence allocator
Date: Wed, 17 Jun 2026 10:27:39 -0400 [thread overview]
Message-ID: <20260617142739.3938338-5-sashal@kernel.org> (raw)
In-Reply-To: <20260617142739.3938338-1-sashal@kernel.org>
From: Tudor Ambarus <tudor.ambarus@linaro.org>
[ Upstream commit bf296f83a3ddab1ab875edc4e8862cb10553064f ]
Sashiko identified memory ordering races in [1].
The ACPM driver uses a globally shared 'bitmap_seqnum' to track
available sequence numbers. Even though threads now strictly free their
own sequence numbers, the allocation and freeing of these bits across
concurrent threads are effectively lockless operations and require
explicit LKMM memory barriers.
Previously, the driver used plain bitwise operators (test_bit, set_bit,
clear_bit), which lack ordering guarantees. This creates two race
conditions on weakly ordered architectures like ARM64:
1. Polling Release Violation: The polling thread copies its payload and
calls clear_bit(). Without a release barrier, the CPU can reorder
the memory operations, making the cleared bit globally visible
before the payload reads have fully completed.
2. TX Acquire Violation: The TX thread loops on test_bit(), calls
set_bit(), and then wipes the payload buffer via memset(). Without
an acquire barrier, the CPU can speculatively execute the memset()
before the bit is safely and formally claimed.
If these reorderings overlap, a new TX thread can claim the sequence
number and overwrite the buffer while the original polling thread is
still actively reading from it.
Fix this by upgrading the bitwise operators. Wrap the TX allocation in
test_and_set_bit_lock() to establish formal LKMM Acquire semantics, and
pair it with clear_bit_unlock() in the polling path to enforce Release
semantics.
Cc: stable@vger.kernel.org
Fixes: a88927b534ba ("firmware: add Exynos ACPM protocol driver")
Closes: https://sashiko.dev/#/patchset/20260423-acpm-fixes-sashiko-reports-v1-0-2217b790925e%40linaro.org [1]
Signed-off-by: Tudor Ambarus <tudor.ambarus@linaro.org>
Link: https://patch.msgid.link/20260505-acpm-fixes-sashiko-reports-v5-6-43b5ee7f1674@linaro.org
Signed-off-by: Krzysztof Kozlowski <krzk@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/firmware/samsung/exynos-acpm.c | 18 +++++++++++-------
1 file changed, 11 insertions(+), 7 deletions(-)
diff --git a/drivers/firmware/samsung/exynos-acpm.c b/drivers/firmware/samsung/exynos-acpm.c
index 7eda1aff4c197b..c472569441949c 100644
--- a/drivers/firmware/samsung/exynos-acpm.c
+++ b/drivers/firmware/samsung/exynos-acpm.c
@@ -7,7 +7,7 @@
#include <linux/bitfield.h>
#include <linux/bitmap.h>
-#include <linux/bits.h>
+#include <linux/bitops.h>
#include <linux/cleanup.h>
#include <linux/container_of.h>
#include <linux/delay.h>
@@ -340,7 +340,7 @@ static int acpm_dequeue_by_polling(struct acpm_chan *achan,
acpm_get_saved_rx(achan, xfer, seqnum);
/* Relinquish ownership of the sequence slot */
- clear_bit(seqnum - 1, achan->bitmap_seqnum);
+ clear_bit_unlock(seqnum - 1, achan->bitmap_seqnum);
return 0;
}
@@ -397,11 +397,18 @@ static void acpm_prepare_xfer(struct acpm_chan *achan,
struct acpm_rx_data *rx_data;
u32 *txd = (u32 *)xfer->txd;
- /* Prevent chan->seqnum from being re-used */
+ /*
+ * Prevent chan->seqnum from being re-used.
+ * test_and_set_bit_lock() provides formal LKMM Acquire semantics.
+ * It pairs with the RX thread's clear_bit_unlock() to ensure the CPU
+ * does not speculatively execute the rx_data buffer wipe (memset)
+ * before the sequence number is safely claimed.
+ */
do {
if (++achan->seqnum == ACPM_SEQNUM_MAX)
achan->seqnum = 1;
- } while (test_bit(achan->seqnum - 1, achan->bitmap_seqnum));
+ /* Flag the index based on seqnum. (seqnum: 1~63, bitmap: 0~62) */
+ } while (test_and_set_bit_lock(achan->seqnum - 1, achan->bitmap_seqnum));
txd[0] |= FIELD_PREP(ACPM_PROTOCOL_SEQNUM, achan->seqnum);
@@ -411,9 +418,6 @@ static void acpm_prepare_xfer(struct acpm_chan *achan,
memset(rx_data->cmd, 0, sizeof(*rx_data->cmd) * rx_data->n_cmd);
/* zero means no response expected */
rx_data->rxcnt = xfer->rxcnt;
-
- /* Flag the index based on seqnum. (seqnum: 1~63, bitmap: 0~62) */
- set_bit(achan->seqnum - 1, achan->bitmap_seqnum);
}
/**
--
2.53.0
prev parent reply other threads:[~2026-06-17 14:27 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-06-15 14:49 FAILED: patch "[PATCH] firmware: samsung: acpm: Fix missing LKMM barriers in" failed to apply to 7.0-stable tree gregkh
2026-06-17 14:27 ` [PATCH 7.0.y 1/5] firmware: exynos-acpm: Count number of commands in acpm_xfer Sasha Levin
2026-06-17 14:27 ` [PATCH 7.0.y 2/5] firmware: exynos-acpm: Count acpm_xfer buffers with __counted_by_ptr Sasha Levin
2026-06-17 14:27 ` [PATCH 7.0.y 3/5] firmware: samsung: acpm: Fix cross-thread RX length corruption Sasha Levin
2026-06-17 14:27 ` [PATCH 7.0.y 4/5] firmware: samsung: acpm: Fix false timeouts and Use-After-Free in polling Sasha Levin
2026-06-17 14:27 ` Sasha Levin [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=20260617142739.3938338-5-sashal@kernel.org \
--to=sashal@kernel.org \
--cc=krzk@kernel.org \
--cc=stable@vger.kernel.org \
--cc=tudor.ambarus@linaro.org \
/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