From c38992f149d796d28a95b2b0c42517b68aa173ea Mon Sep 17 00:00:00 2001 From: Mohammad Rafi Shaik Date: Tue, 21 Apr 2026 23:33:07 +0530 Subject: [PATCH] audioreach-driver: q6apm_audio_pkt: Fix crash issue after command timeout during SSR Fix crash issue after command timeout during SSR. In q6apm_send_audio_cmd_sync(), the dev_err() calls on the command timeout and DSP error paths were using the 'dev' parameter passed into the function. During SSR, this device pointer may no longer be valid, leading to a NULL pointer dereference or use-after-free. Fix this by switching to &g_apm->adev->dev, which refers to the stable global APM device and remains valid across SSR events. In audio_pkt_release(), the audpkt_dev pointer was being obtained via cdev_to_audpkt_dev(inode->i_cdev). During SSR, the inode's cdev may have already been torn down or become invalid by the time release() is called, resulting in a crash when dereferencing the pointer. Fix this by retrieving audpkt_dev from file->private_data, which is set during audio_pkt_open() and remains valid for the lifetime of the open file descriptor. Additionally, add a NULL check guard for audpkt_dev and audpkt_dev->dev at the start of the function to safely handle any edge cases where the private data may not have been properly initialized. Signed-off-by: Mohammad Rafi Shaik --- audioreach-driver/q6apm_audio_pkt.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/audioreach-driver/q6apm_audio_pkt.c b/audioreach-driver/q6apm_audio_pkt.c index 5497c3e..4dc6f7a 100644 --- a/audioreach-driver/q6apm_audio_pkt.c +++ b/audioreach-driver/q6apm_audio_pkt.c @@ -155,10 +155,11 @@ static int q6apm_send_audio_cmd_sync(struct device *dev, gpr_device_t *gdev, rc = wait_event_timeout(*cmd_wait, (result->opcode == hdr->opcode), wait_time * HZ); if (!rc) { - dev_err(dev, "CMD timeout for [%x] opcode\n", hdr->opcode); + dev_err(&g_apm->adev->dev, "CMD timeout for [%x] opcode\n", hdr->opcode); rc = -ETIMEDOUT; } else if (result->status > 0) { - dev_err(dev, "DSP returned error[%x] %x\n", hdr->opcode, result->status); + dev_err(&g_apm->adev->dev, "DSP returned error[%x] %x\n", hdr->opcode, + result->status); rc = -EINVAL; } else { /* DSP successfully finished the command */ @@ -280,11 +281,14 @@ static int audio_pkt_open(struct inode *inode, struct file *file) */ static int audio_pkt_release(struct inode *inode, struct file *file) { - struct q6apm_audio_pkt *audpkt_dev = cdev_to_audpkt_dev(inode->i_cdev); + struct q6apm_audio_pkt *audpkt_dev = file->private_data; struct device *dev = audpkt_dev->dev; struct sk_buff *skb; unsigned long flags; + if (!audpkt_dev || !audpkt_dev->dev) + return -EINVAL; + spin_lock_irqsave(&audpkt_dev->queue_lock, flags); /* Discard all SKBs */ @@ -684,6 +688,7 @@ static void q6apm_audio_pkt_remove(gpr_device_t *adev) unregister_chrdev_region(apm->audio_pkt_major, MINOR_NUMBER_COUNT); dev_set_drvdata(dev, NULL); + g_apm = NULL; } #ifdef CONFIG_OF