Commit acacd9ee authored by Peter Ujfalusi's avatar Peter Ujfalusi Committed by Mark Brown

ASoC: SOF: Intel: cnl: 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-2-peter.ujfalusi@linux.intel.comSigned-off-by: default avatarMark Brown <broonie@kernel.org>
parent 388fe2b8
...@@ -60,17 +60,23 @@ irqreturn_t cnl_ipc4_irq_thread(int irq, void *context) ...@@ -60,17 +60,23 @@ irqreturn_t cnl_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 */
notification_data.primary = primary; notification_data.primary = primary;
...@@ -124,15 +130,20 @@ irqreturn_t cnl_ipc_irq_thread(int irq, void *context) ...@@ -124,15 +130,20 @@ irqreturn_t cnl_ipc_irq_thread(int irq, void *context)
CNL_DSP_REG_HIPCCTL, CNL_DSP_REG_HIPCCTL,
CNL_DSP_REG_HIPCCTL_DONE, 0); CNL_DSP_REG_HIPCCTL_DONE, 0);
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);
cnl_ipc_dsp_done(sdev); cnl_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