VYPR
Unrated severityNVD Advisory· Published May 28, 2026

CVE-2026-46143

CVE-2026-46143

Description

In the Linux kernel, the following vulnerability has been resolved:

ASoC: qcom: q6apm-lpass-dai: Fix multiple graph opens

As prepare can be called mulitple times, this can result in multiple graph opens for playback path.

This will result in a memory leaks, fix this by adding a check before opening.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

A memory leak in the Linux kernel's ASoC q6apm-lpass-dai driver occurs when prepare is called multiple times without checking for an existing graph open.

Vulnerability

In the Linux kernel, in the ASoC QCOM q6apm-lpass-dai driver, the prepare callback can be invoked multiple times for the same playback path. Each invocation opens a new graph without first checking whether one is already open, leading to an unintended sequence of multiple graph opens. This affects kernel versions up to and including the commit before the fix referenced in [1].

Exploitation

An attacker would need local access and the ability to trigger multiple prepare calls on a sound card playback stream — possibly via repeated ALSA PCM preparation requests from userspace. No special privileges beyond basic audio subsystem access are required. The sequence is: (1) open the PCM device, (2) call snd_pcm_prepare multiple times, (3) each call triggers a new graph open without closing the previous one.

Impact

Each extra graph open leaks kernel memory associated with the graph allocation. Over repeated or automated calls, this can lead to memory exhaustion and system instability. The impact is limited to denial of service (resource exhaustion); no privilege escalation or information disclosure is described [1].

Mitigation

The fix was committed to the stable kernel tree as commit 3141d8b00cad [1]. It adds a check before opening a new graph, preventing duplicate opens. Users should apply the patch or update to a kernel version that includes this commit. No workaround short of the patch is provided in the available references.

AI Insight generated on May 28, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected products

1

Patches

10
c91b7bcc7034

ASoC: qcom: q6apm-lpass-dai: Fix multiple graph opens

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitSrinivas KandagatlaFixed in 6.12.88via kernel-cna
1 file changed · +1 2
  • sound/soc/qcom/qdsp6/q6apm-lpass-dais.c+1 2 modified
    diff --git a/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c b/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c
    index cba8548415ad52..b33864ae529f5b 100644
    --- a/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c
    +++ b/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c
    @@ -181,7 +181,7 @@ static int q6apm_lpass_dai_prepare(struct snd_pcm_substream *substream, struct s
     	 * It is recommend to load DSP with source graph first and then sink
     	 * graph, so sequence for playback and capture will be different
     	 */
    -	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
    +	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && dai_data->graph[dai->id] == NULL) {
     		graph = q6apm_graph_open(dai->dev, NULL, dai->dev, graph_id);
     		if (IS_ERR(graph)) {
     			dev_err(dai->dev, "Failed to open graph (%d)\n", graph_id);
    -- 
    cgit 1.3-korg
    
    
    
7cab9f2ad51c

ASoC: qcom: q6apm-lpass-dai: Fix multiple graph opens

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitSrinivas KandagatlaFixed in 6.18.30via kernel-cna
1 file changed · +1 2
  • sound/soc/qcom/qdsp6/q6apm-lpass-dais.c+1 2 modified
    diff --git a/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c b/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c
    index 5be37eeea329fc..ba64117b8cfe13 100644
    --- a/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c
    +++ b/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c
    @@ -181,7 +181,7 @@ static int q6apm_lpass_dai_prepare(struct snd_pcm_substream *substream, struct s
     	 * It is recommend to load DSP with source graph first and then sink
     	 * graph, so sequence for playback and capture will be different
     	 */
    -	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
    +	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && dai_data->graph[dai->id] == NULL) {
     		graph = q6apm_graph_open(dai->dev, NULL, dai->dev, graph_id);
     		if (IS_ERR(graph)) {
     			dev_err(dai->dev, "Failed to open graph (%d)\n", graph_id);
    -- 
    cgit 1.3-korg
    
    
    
3141d8b00cad

ASoC: qcom: q6apm-lpass-dai: Fix multiple graph opens

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitSrinivas KandagatlaFixed in 6.6.140via kernel-cna
1 file changed · +1 2
  • sound/soc/qcom/qdsp6/q6apm-lpass-dais.c+1 2 modified
    diff --git a/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c b/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c
    index 9fcf8f59ea280a..8f8fb537876f95 100644
    --- a/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c
    +++ b/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c
    @@ -175,7 +175,7 @@ static int q6apm_lpass_dai_prepare(struct snd_pcm_substream *substream, struct s
     	 * It is recommend to load DSP with source graph first and then sink
     	 * graph, so sequence for playback and capture will be different
     	 */
    -	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
    +	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && dai_data->graph[dai->id] == NULL) {
     		graph = q6apm_graph_open(dai->dev, NULL, dai->dev, graph_id);
     		if (IS_ERR(graph)) {
     			dev_err(dai->dev, "Failed to open graph (%d)\n", graph_id);
    -- 
    cgit 1.3-korg
    
    
    
69acc488aaf3

ASoC: qcom: q6apm-lpass-dai: Fix multiple graph opens

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitSrinivas KandagatlaFixed in 7.1-rc1via kernel-cna
1 file changed · +1 2
  • sound/soc/qcom/qdsp6/q6apm-lpass-dais.c+1 2 modified
    diff --git a/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c b/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c
    index 5be37eeea329fc..ba64117b8cfe13 100644
    --- a/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c
    +++ b/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c
    @@ -181,7 +181,7 @@ static int q6apm_lpass_dai_prepare(struct snd_pcm_substream *substream, struct s
     	 * It is recommend to load DSP with source graph first and then sink
     	 * graph, so sequence for playback and capture will be different
     	 */
    -	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
    +	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && dai_data->graph[dai->id] == NULL) {
     		graph = q6apm_graph_open(dai->dev, NULL, dai->dev, graph_id);
     		if (IS_ERR(graph)) {
     			dev_err(dai->dev, "Failed to open graph (%d)\n", graph_id);
    -- 
    cgit 1.3-korg
    
    
    
b97493f0f42a

ASoC: qcom: q6apm-lpass-dai: Fix multiple graph opens

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitSrinivas KandagatlaFixed in 7.0.7via kernel-cna
1 file changed · +1 2
  • sound/soc/qcom/qdsp6/q6apm-lpass-dais.c+1 2 modified
    diff --git a/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c b/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c
    index 5be37eeea329fc..ba64117b8cfe13 100644
    --- a/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c
    +++ b/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c
    @@ -181,7 +181,7 @@ static int q6apm_lpass_dai_prepare(struct snd_pcm_substream *substream, struct s
     	 * It is recommend to load DSP with source graph first and then sink
     	 * graph, so sequence for playback and capture will be different
     	 */
    -	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
    +	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && dai_data->graph[dai->id] == NULL) {
     		graph = q6apm_graph_open(dai->dev, NULL, dai->dev, graph_id);
     		if (IS_ERR(graph)) {
     			dev_err(dai->dev, "Failed to open graph (%d)\n", graph_id);
    -- 
    cgit 1.3-korg
    
    
    
b97493f0f42a

ASoC: qcom: q6apm-lpass-dai: Fix multiple graph opens

1 file changed · +1 2
  • sound/soc/qcom/qdsp6/q6apm-lpass-dais.c+1 2 modified
    diff --git a/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c b/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c
    index 5be37eeea329fc..ba64117b8cfe13 100644
    --- a/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c
    +++ b/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c
    @@ -181,7 +181,7 @@ static int q6apm_lpass_dai_prepare(struct snd_pcm_substream *substream, struct s
     	 * It is recommend to load DSP with source graph first and then sink
     	 * graph, so sequence for playback and capture will be different
     	 */
    -	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
    +	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && dai_data->graph[dai->id] == NULL) {
     		graph = q6apm_graph_open(dai->dev, NULL, dai->dev, graph_id);
     		if (IS_ERR(graph)) {
     			dev_err(dai->dev, "Failed to open graph (%d)\n", graph_id);
    -- 
    cgit 1.3-korg
    
    
    
7cab9f2ad51c

ASoC: qcom: q6apm-lpass-dai: Fix multiple graph opens

1 file changed · +1 2
  • sound/soc/qcom/qdsp6/q6apm-lpass-dais.c+1 2 modified
    diff --git a/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c b/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c
    index 5be37eeea329fc..ba64117b8cfe13 100644
    --- a/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c
    +++ b/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c
    @@ -181,7 +181,7 @@ static int q6apm_lpass_dai_prepare(struct snd_pcm_substream *substream, struct s
     	 * It is recommend to load DSP with source graph first and then sink
     	 * graph, so sequence for playback and capture will be different
     	 */
    -	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
    +	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && dai_data->graph[dai->id] == NULL) {
     		graph = q6apm_graph_open(dai->dev, NULL, dai->dev, graph_id);
     		if (IS_ERR(graph)) {
     			dev_err(dai->dev, "Failed to open graph (%d)\n", graph_id);
    -- 
    cgit 1.3-korg
    
    
    
3141d8b00cad

ASoC: qcom: q6apm-lpass-dai: Fix multiple graph opens

1 file changed · +1 2
  • sound/soc/qcom/qdsp6/q6apm-lpass-dais.c+1 2 modified
    diff --git a/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c b/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c
    index 9fcf8f59ea280a..8f8fb537876f95 100644
    --- a/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c
    +++ b/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c
    @@ -175,7 +175,7 @@ static int q6apm_lpass_dai_prepare(struct snd_pcm_substream *substream, struct s
     	 * It is recommend to load DSP with source graph first and then sink
     	 * graph, so sequence for playback and capture will be different
     	 */
    -	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
    +	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && dai_data->graph[dai->id] == NULL) {
     		graph = q6apm_graph_open(dai->dev, NULL, dai->dev, graph_id);
     		if (IS_ERR(graph)) {
     			dev_err(dai->dev, "Failed to open graph (%d)\n", graph_id);
    -- 
    cgit 1.3-korg
    
    
    
69acc488aaf3

ASoC: qcom: q6apm-lpass-dai: Fix multiple graph opens

1 file changed · +1 2
  • sound/soc/qcom/qdsp6/q6apm-lpass-dais.c+1 2 modified
    diff --git a/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c b/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c
    index 5be37eeea329fc..ba64117b8cfe13 100644
    --- a/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c
    +++ b/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c
    @@ -181,7 +181,7 @@ static int q6apm_lpass_dai_prepare(struct snd_pcm_substream *substream, struct s
     	 * It is recommend to load DSP with source graph first and then sink
     	 * graph, so sequence for playback and capture will be different
     	 */
    -	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
    +	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && dai_data->graph[dai->id] == NULL) {
     		graph = q6apm_graph_open(dai->dev, NULL, dai->dev, graph_id);
     		if (IS_ERR(graph)) {
     			dev_err(dai->dev, "Failed to open graph (%d)\n", graph_id);
    -- 
    cgit 1.3-korg
    
    
    
c91b7bcc7034

ASoC: qcom: q6apm-lpass-dai: Fix multiple graph opens

1 file changed · +1 2
  • sound/soc/qcom/qdsp6/q6apm-lpass-dais.c+1 2 modified
    diff --git a/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c b/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c
    index cba8548415ad52..b33864ae529f5b 100644
    --- a/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c
    +++ b/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c
    @@ -181,7 +181,7 @@ static int q6apm_lpass_dai_prepare(struct snd_pcm_substream *substream, struct s
     	 * It is recommend to load DSP with source graph first and then sink
     	 * graph, so sequence for playback and capture will be different
     	 */
    -	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
    +	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && dai_data->graph[dai->id] == NULL) {
     		graph = q6apm_graph_open(dai->dev, NULL, dai->dev, graph_id);
     		if (IS_ERR(graph)) {
     			dev_err(dai->dev, "Failed to open graph (%d)\n", graph_id);
    -- 
    cgit 1.3-korg
    
    
    

Vulnerability mechanics

Root cause

"Missing idempotency check in `q6apm_lpass_dai_prepare` allows `q6apm_graph_open` to be called multiple times for the same playback DAI, leaking memory."

Attack vector

An attacker who can trigger repeated `prepare` calls on a playback PCM substream (e.g., via ALSA `snd_pcm_prepare` or audio framework operations) will cause `q6apm_graph_open` to be invoked multiple times for the same DAI. Each call allocates a new graph object, but the previous pointer is overwritten without being freed, leading to a memory leak. No special network path or authentication is required; the attacker only needs the ability to interact with the ALSA PCM interface on a Qualcomm ASoC system using the q6apm-lpass-dai driver.

Affected code

The vulnerability is in the `q6apm_lpass_dai_prepare` function in `sound/soc/qcom/qdsp6/q6apm-lpass-dais.c` [patch_id=2898331]. The function unconditionally calls `q6apm_graph_open` for the playback stream without checking whether the graph pointer (`dai_data->graph[dai->id]`) is already non-NULL.

What the fix does

The patch adds a guard condition `dai_data->graph[dai->id] == NULL` to the existing playback-stream check [patch_id=2898331]. Before calling `q6apm_graph_open`, the code now verifies that no graph has already been opened for that DAI. If the pointer is non-NULL, the open is skipped, preventing duplicate allocations and the resulting memory leak. This is a minimal, targeted fix that does not alter any other control flow.

Preconditions

  • inputThe attacker must be able to invoke the ALSA `prepare` operation multiple times on a playback PCM substream.
  • configThe system must use the Qualcomm ASoC q6apm-lpass-dai driver with a playback path configured.

Generated on May 28, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

5

News mentions

0

No linked articles in our index yet.