]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
ASoC: qcom: q6apm: fix NULL pointer dereference in graph_callback
authorSrinivas Kandagatla <srinivas.kandagatla@oss.qualcomm.com>
Tue, 16 Jun 2026 17:02:57 +0000 (18:02 +0100)
committerMark Brown <broonie@kernel.org>
Wed, 17 Jun 2026 12:50:03 +0000 (13:50 +0100)
When q6apm_free_fragments() is called it frees rx_data.buf/tx_data.buf
and sets them to NULL under graph->lock. A late DSP buffer-done response
can race with this: graph_callback() passes the !graph->ar_graph guard
(not yet NULL), acquires the lock, but then dereferences a now-NULL buf
pointer to read buf[token].phys, crashing at virtual address 0x10.

Add a NULL check for buf inside the mutex-protected section in both the
write-done (DATA_CMD_RSP_WR_SH_MEM_EP_DATA_BUFFER_DONE_V2) and
read-done (DATA_CMD_RSP_RD_SH_MEM_EP_DATA_BUFFER_V2) handlers and bail
out cleanly if buffers have already been freed.

This problem is only shown up recently while apr bus was updated to
process the commands per service rather from single global queue.

Fixes: 5477518b8a0e ("ASoC: qdsp6: audioreach: add q6apm support")
Cc: Stable@vger.kernel.org
Assisted-by: Claude:claude-4-6-sonnet
Reported-by: Val Packett <val@packett.cool>
Closes: https://lore.kernel.org/all/133ced18-1aa9-475d-80d8-6120678bdde4@packett.cool/
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@oss.qualcomm.com>
Link: https://patch.msgid.link/20260616170257.9381-1-srinivas.kandagatla@oss.qualcomm.com
Signed-off-by: Mark Brown <broonie@kernel.org>
sound/soc/qcom/qdsp6/q6apm.c

index 2e5b25b8d00fd3f9b4646b0b4d43c57e99b777c1..641d6d24322990944fe76446ffe9f43e807e3aab 100644 (file)
@@ -587,6 +587,10 @@ static int graph_callback(const struct gpr_resp_pkt *data, void *priv, int op)
                token = hdr->token & APM_WRITE_TOKEN_MASK;
 
                done = data->payload;
+               if (!graph->rx_data.buf) {
+                       mutex_unlock(&graph->lock);
+                       break;
+               }
                phys = graph->rx_data.buf[token].phys;
                mutex_unlock(&graph->lock);
                /* token numbering starts at 0 */
@@ -609,6 +613,10 @@ static int graph_callback(const struct gpr_resp_pkt *data, void *priv, int op)
                client_event = APM_CLIENT_EVENT_DATA_READ_DONE;
                mutex_lock(&graph->lock);
                rd_done = data->payload;
+               if (!graph->tx_data.buf) {
+                       mutex_unlock(&graph->lock);
+                       break;
+               }
                phys = graph->tx_data.buf[hdr->token].phys;
                mutex_unlock(&graph->lock);
                /* token numbering starts at 0 */