From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Pawel Furtak Date: Tue, 5 Mar 2019 09:19:19 +0100 Subject: [PATCH] ASoC: Intel: Skl: Virt: Fix panic during tplg initialization Timeout during topology request may lead to not initialized topology buffer. This patch adds additional checks and cleanups to avoid access fo not initialized/freed memory. Change-Id: I1a4eec1c04d41566e04a58fd88e4307c01a39664 Tracked-On: OAM-76719 Signed-off-by: Pawel Furtak Signed-off-by: Wojciech Jablonski --- .../soc/intel/skylake/virtio/skl-virtio-fe.c | 27 +++++++++++++------ 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/sound/soc/intel/skylake/virtio/skl-virtio-fe.c b/sound/soc/intel/skylake/virtio/skl-virtio-fe.c index 8b54d0808eb9..17d5e3de45f5 100644 --- a/sound/soc/intel/skylake/virtio/skl-virtio-fe.c +++ b/sound/soc/intel/skylake/virtio/skl-virtio-fe.c @@ -282,7 +282,6 @@ static void vfe_cmd_handle_rx(struct virtqueue *vq) vfe = vq->vdev->priv; - spin_lock_irqsave(&vfe->substream_info_lock, irq_flags); list_for_each_entry_safe(substr_info, tmp, &vfe->substr_info_list, list) { @@ -414,7 +413,11 @@ static void vfe_handle_tplg(struct snd_skl_vfe *vfe, tplg_data->offset, tplg_data->chunk_size); mutex_lock(&vfe->tplg.tplg_lock); - data_ptr = vfe->tplg.tplg_data.data + tplg_data->offset; + + if (!vfe->tplg.tplg_data.data) + goto err_handler; + + data_ptr = (u8 *)vfe->tplg.tplg_data.data + tplg_data->offset; memcpy(data_ptr, tplg_data->data, tplg_data->chunk_size); vfe->tplg.data_ready += tplg_data->chunk_size; @@ -423,6 +426,7 @@ static void vfe_handle_tplg(struct snd_skl_vfe *vfe, wake_up(&vfe->tplg.waitq); } +err_handler: mutex_unlock(&vfe->tplg.tplg_lock); } @@ -1018,7 +1022,7 @@ static int vfe_skl_init(struct virtio_device *vdev) err = vfe_init_tplg(vfe, skl); if (err < 0) - return err; + goto error; err = vfe_platform_register(vfe, &vdev->dev); if (err < 0) @@ -1087,8 +1091,10 @@ static int vfe_init(struct virtio_device *vdev) int ret; vfe = devm_kzalloc(&vdev->dev, sizeof(*vfe), GFP_KERNEL); - if (!vfe) - goto no_mem; + if (!vfe) { + ret = -ENOMEM; + goto err; + } skl_vfe = vfe; vfe->vdev = vdev; @@ -1123,12 +1129,17 @@ static int vfe_init(struct virtio_device *vdev) ret = vfe_skl_init(vdev); if (ret < 0) - goto err; + goto skl_err; return 0; -no_mem: - ret = -ENOMEM; +skl_err: + virtqueue_disable_cb(vfe->ipc_not_tx_vq); + virtqueue_disable_cb(vfe->ipc_not_rx_vq); + cancel_work_sync(&vfe->msg_timeout_work); + cancel_work_sync(&vfe->message_loop_work); + vdev->config->reset(vdev); + vdev->config->del_vqs(vdev); err: vdev->priv = NULL; return ret; -- https://clearlinux.org