From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 563753F0ABE for ; Wed, 17 Jun 2026 14:27:43 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1781706464; cv=none; b=Gh+J1aVpE6mtRKeRmauaO/lI+1uTOzyEjg09VlmhsGbY9aoIuKnF1sTwxESkQSu+OyT9qUknusSOaF9sKTJ9Bvh2eVugtTLYsFDGrEXmet4R/dtE1MvxGD4tvciudRyOf4y/+f3AnJqdkDwkyW7WXVZxVYPPdJqoIqPyW/LyR7M= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1781706464; c=relaxed/simple; bh=3VY6yww+8m2KXg17u6VAUdYQ/58AWi2t9i5JGmXa7tg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=IR9e7vFrg0MLhBmad3nQIooQKm868LOZjTNxhVSJXCTkGJVIjjyX3c+kdnHJBRArd8GNZr2Fyjo+SwpHcMyvrkyZThygAZUC4q4NdcM5VF2SMuAiphR9qMxiogW+k2Qvd3ZiU6nzC7lhnyD913679Adrq/zmT5r6ohRmnB3NbC0= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=PJaKLhQL; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="PJaKLhQL" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 9B7961F00A3A; Wed, 17 Jun 2026 14:27:42 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1781706463; bh=UAlvGHB3TvYkxjAVlvsrKgqWS5LsiVeu9v3D9iYnXoM=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=PJaKLhQLgF2UX8qTKQBbxJV2kWzIV2ZotkfJo34Btutdxg8f5l8jvd1hWERdqfEUE JOn8FTW4VX0iDcRDJtlnd2viE2ErXldANJjA+kit5gqfoPBFvjy8bwEFg1v7S/h2Fd 76gHFhhDekCgw5zLtVQGGQS50l9w63vKqc3Xo9dpwR/MJpMLxTOnnXf0w4uVXRlQ5L IQrf6jWApYjak2+r5AUsXg3w8HawBvR47FcwZ/jYnO8SPqI8afMO0OmkINsdHlWi8a O7VTsXPZslTSAq3INxxVd/2V4JPP1YQruscShf+/C7+Rr3eoC7LnhEbtEdQ+aLtlKL Y5CPraLLburcQ== From: Sasha Levin To: stable@vger.kernel.org Cc: Tudor Ambarus , Titouan Ameline de Cadeville , Krzysztof Kozlowski , Sasha Levin Subject: [PATCH 7.0.y 3/5] firmware: samsung: acpm: Fix cross-thread RX length corruption Date: Wed, 17 Jun 2026 10:27:37 -0400 Message-ID: <20260617142739.3938338-3-sashal@kernel.org> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260617142739.3938338-1-sashal@kernel.org> References: <2026061551-lung-clutter-0849@gregkh> <20260617142739.3938338-1-sashal@kernel.org> Precedence: bulk X-Mailing-List: stable@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit From: Tudor Ambarus [ Upstream commit f133bd4b5daf71bccdde0ad1a4f47fac76a6bfb1 ] Sashiko identified a cross-thread RX length corruption bug when reviewing the thermal addition to ACPM [1]. When multiple threads concurrently send IPC requests, the ACPM polling mechanism can encounter responses belonging to other threads. To drain the queue, the driver saves these concurrent responses into an internal cache (`rx_data->cmd`) to be retrieved later by the owning thread. Previously, the driver incorrectly used `xfer->rxcnt` (the expected receive length of the *current* polling thread) when copying data for *other* threads into this cache. If the threads expected responses of different lengths, this resulted in buffer underflows (leading to reads of uninitialized memory) or potential buffer overflows. Fix this by replacing the boolean `response` flag in `struct acpm_rx_data` with `rxcnt`, caching the exact expected receive length for each specific transaction during transfer preparation. Use this cached length when saving concurrent responses. Consequently, ensure that `xfer->rxcnt` is explicitly zeroed in driver helpers (e.g., `acpm_dvfs_set_xfer`) for fire-and-forget messages to prevent uninitialized stack garbage from being interpreted as a massive expected receive length. Cc: stable@vger.kernel.org Fixes: a88927b534ba ("firmware: add Exynos ACPM protocol driver") Closes: https://sashiko.dev/#/patchset/20260420-acpm-tmu-v3-0-3dc8e93f0b26%40linaro.org [1] Reported-by: Titouan Ameline de Cadeville Closes: https://lore.kernel.org/r/20260426210255.73674-1-titouan.ameline@gmail.com/ Signed-off-by: Tudor Ambarus Link: https://patch.msgid.link/20260505-acpm-fixes-sashiko-reports-v5-1-43b5ee7f1674@linaro.org Signed-off-by: Krzysztof Kozlowski Stable-dep-of: bf296f83a3dd ("firmware: samsung: acpm: Fix missing LKMM barriers in sequence allocator") Signed-off-by: Sasha Levin --- drivers/firmware/samsung/exynos-acpm-dvfs.c | 3 +++ drivers/firmware/samsung/exynos-acpm.c | 15 ++++++++------- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/drivers/firmware/samsung/exynos-acpm-dvfs.c b/drivers/firmware/samsung/exynos-acpm-dvfs.c index 06bdf62dea1f30..fdea7aa24ca02e 100644 --- a/drivers/firmware/samsung/exynos-acpm-dvfs.c +++ b/drivers/firmware/samsung/exynos-acpm-dvfs.c @@ -31,6 +31,9 @@ static void acpm_dvfs_set_xfer(struct acpm_xfer *xfer, u32 *cmd, size_t cmdlen, if (response) { xfer->rxcnt = cmdlen; xfer->rxd = cmd; + } else { + xfer->rxcnt = 0; + xfer->rxd = NULL; } } diff --git a/drivers/firmware/samsung/exynos-acpm.c b/drivers/firmware/samsung/exynos-acpm.c index 16c46ed6083716..e95edc350efa6c 100644 --- a/drivers/firmware/samsung/exynos-acpm.c +++ b/drivers/firmware/samsung/exynos-acpm.c @@ -104,12 +104,12 @@ struct acpm_queue { * * @cmd: pointer to where the data shall be saved. * @n_cmd: number of 32-bit commands. - * @response: true if the client expects the RX data. + * @rxcnt: expected length of the response in 32-bit words. */ struct acpm_rx_data { u32 *cmd; size_t n_cmd; - bool response; + size_t rxcnt; }; #define ACPM_SEQNUM_MAX 64 @@ -199,7 +199,7 @@ static void acpm_get_saved_rx(struct acpm_chan *achan, const struct acpm_rx_data *rx_data = &achan->rx_data[tx_seqnum - 1]; u32 rx_seqnum; - if (!rx_data->response) + if (!rx_data->rxcnt) return; rx_seqnum = FIELD_GET(ACPM_PROTOCOL_SEQNUM, rx_data->cmd[0]); @@ -256,7 +256,7 @@ static int acpm_get_rx(struct acpm_chan *achan, const struct acpm_xfer *xfer) seqnum = rx_seqnum - 1; rx_data = &achan->rx_data[seqnum]; - if (rx_data->response) { + if (rx_data->rxcnt) { if (rx_seqnum == tx_seqnum) { __ioread32_copy(xfer->rxd, addr, xfer->rxcnt); rx_set = true; @@ -268,7 +268,8 @@ static int acpm_get_rx(struct acpm_chan *achan, const struct acpm_xfer *xfer) * clear yet the bitmap. It will be cleared * after the response is copied to the request. */ - __ioread32_copy(rx_data->cmd, addr, xfer->rxcnt); + __ioread32_copy(rx_data->cmd, addr, + rx_data->rxcnt); } } else { clear_bit(seqnum, achan->bitmap_seqnum); @@ -380,8 +381,8 @@ static void acpm_prepare_xfer(struct acpm_chan *achan, /* Clear data for upcoming responses */ rx_data = &achan->rx_data[achan->seqnum - 1]; memset(rx_data->cmd, 0, sizeof(*rx_data->cmd) * rx_data->n_cmd); - if (xfer->rxd) - rx_data->response = true; + /* 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