Commit 499cc881 authored by Peter Ujfalusi's avatar Peter Ujfalusi Committed by Mark Brown

ASoC: SOF: Intel: hda-ipc: Do not process IPC reply before firmware boot

It is not yet clear, but it is possible to create a firmware so broken
that it will send a reply message before a FW_READY message (it is not
yet clear if FW_READY will arrive later).
Since the reply_data is allocated only after the FW_READY message, this
will lead to a NULL pointer dereference if not filtered out.

The issue was reported with IPC4 firmware but the same condition is present
for IPC3.
Reported-by: default avatarKai Vehmanen <kai.vehmanen@linux.intel.com>
Signed-off-by: default avatarPeter Ujfalusi <peter.ujfalusi@linux.intel.com>
Reviewed-by: default avatarRanjani Sridharan <ranjani.sridharan@linux.intel.com>
Reviewed-by: default avatarPierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Link: https://lore.kernel.org/r/20220712122357.31282-3-peter.ujfalusi@linux.intel.comSigned-off-by: default avatarMark Brown <broonie@kernel.org>
parent acacd9ee
...@@ -148,17 +148,23 @@ irqreturn_t hda_dsp_ipc4_irq_thread(int irq, void *context) ...@@ -148,17 +148,23 @@ irqreturn_t hda_dsp_ipc4_irq_thread(int irq, void *context)
if (primary & SOF_IPC4_MSG_DIR_MASK) { if (primary & SOF_IPC4_MSG_DIR_MASK) {
/* Reply received */ /* Reply received */
struct sof_ipc4_msg *data = sdev->ipc->msg.reply_data; if (likely(sdev->fw_state == SOF_FW_BOOT_COMPLETE)) {
struct sof_ipc4_msg *data = sdev->ipc->msg.reply_data;
data->primary = primary; data->primary = primary;
data->extension = extension; data->extension = extension;
spin_lock_irq(&sdev->ipc_lock); spin_lock_irq(&sdev->ipc_lock);
snd_sof_ipc_get_reply(sdev); snd_sof_ipc_get_reply(sdev);
snd_sof_ipc_reply(sdev, data->primary); snd_sof_ipc_reply(sdev, data->primary);
spin_unlock_irq(&sdev->ipc_lock); spin_unlock_irq(&sdev->ipc_lock);
} else {
dev_dbg_ratelimited(sdev->dev,
"IPC reply before FW_READY: %#x|%#x\n",
primary, extension);
}
} else { } else {
/* Notification received */ /* Notification received */
...@@ -225,16 +231,21 @@ irqreturn_t hda_dsp_ipc_irq_thread(int irq, void *context) ...@@ -225,16 +231,21 @@ irqreturn_t hda_dsp_ipc_irq_thread(int irq, void *context)
* place, the message might not yet be marked as expecting a * place, the message might not yet be marked as expecting a
* reply. * reply.
*/ */
spin_lock_irq(&sdev->ipc_lock); if (likely(sdev->fw_state == SOF_FW_BOOT_COMPLETE)) {
spin_lock_irq(&sdev->ipc_lock);
/* handle immediate reply from DSP core */ /* handle immediate reply from DSP core */
hda_dsp_ipc_get_reply(sdev); hda_dsp_ipc_get_reply(sdev);
snd_sof_ipc_reply(sdev, msg); snd_sof_ipc_reply(sdev, msg);
/* set the done bit */ /* set the done bit */
hda_dsp_ipc_dsp_done(sdev); hda_dsp_ipc_dsp_done(sdev);
spin_unlock_irq(&sdev->ipc_lock); spin_unlock_irq(&sdev->ipc_lock);
} else {
dev_dbg_ratelimited(sdev->dev, "IPC reply before FW_READY: %#x\n",
msg);
}
ipc_irq = true; ipc_irq = true;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment