ASoC: SOF: ipc4-mtrace: protect per-core nodes against multiple open
authorKai Vehmanen <kai.vehmanen@linux.intel.com>
Tue, 18 Oct 2022 12:13:32 +0000 (15:13 +0300)
committerMark Brown <broonie@kernel.org>
Tue, 18 Oct 2022 20:17:21 +0000 (21:17 +0100)
Add protection against multiple open of the mtrace/coreN debugfs
nodes. This is not supported in the implementation, and this will
show up as unexpected behaviour of the interface, and potential
use of already freed memory.

Fixes: f4ea22f7aa75 ("ASoC: SOF: ipc4: Add support for mtrace log extraction")
Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
Reviewed-by: Péter Ujfalusi <peter.ujfalusi@linux.intel.com>
Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Reviewed-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
Link: https://lore.kernel.org/r/20221018121332.20802-1-peter.ujfalusi@linux.intel.com
Signed-off-by: Mark Brown <broonie@kernel.org>
sound/soc/sof/ipc4-mtrace.c

index 9c7080041d0828caa122f0a37c09a461cf03981e..70dea8ae706e97b3cdae3cdf879765e21234a2ff 100644 (file)
@@ -108,6 +108,7 @@ struct sof_mtrace_core_data {
        int id;
        u32 slot_offset;
        void *log_buffer;
+       struct mutex buffer_lock; /* for log_buffer alloc/free */
        u32 host_read_ptr;
        u32 dsp_write_ptr;
        /* pos update IPC arrived before the slot offset is known, queried */
@@ -128,14 +129,22 @@ static int sof_ipc4_mtrace_dfs_open(struct inode *inode, struct file *file)
        struct sof_mtrace_core_data *core_data = inode->i_private;
        int ret;
 
+       mutex_lock(&core_data->buffer_lock);
+
+       if (core_data->log_buffer) {
+               ret = -EBUSY;
+               goto out;
+       }
+
        ret = debugfs_file_get(file->f_path.dentry);
        if (unlikely(ret))
-               return ret;
+               goto out;
 
        core_data->log_buffer = kmalloc(SOF_MTRACE_SLOT_SIZE, GFP_KERNEL);
        if (!core_data->log_buffer) {
                debugfs_file_put(file->f_path.dentry);
-               return -ENOMEM;
+               ret = -ENOMEM;
+               goto out;
        }
 
        ret = simple_open(inode, file);
@@ -144,6 +153,9 @@ static int sof_ipc4_mtrace_dfs_open(struct inode *inode, struct file *file)
                debugfs_file_put(file->f_path.dentry);
        }
 
+out:
+       mutex_unlock(&core_data->buffer_lock);
+
        return ret;
 }
 
@@ -280,7 +292,10 @@ static int sof_ipc4_mtrace_dfs_release(struct inode *inode, struct file *file)
 
        debugfs_file_put(file->f_path.dentry);
 
+       mutex_lock(&core_data->buffer_lock);
        kfree(core_data->log_buffer);
+       core_data->log_buffer = NULL;
+       mutex_unlock(&core_data->buffer_lock);
 
        return 0;
 }
@@ -563,6 +578,7 @@ static int ipc4_mtrace_init(struct snd_sof_dev *sdev)
                struct sof_mtrace_core_data *core_data = &priv->cores[i];
 
                init_waitqueue_head(&core_data->trace_sleep);
+               mutex_init(&core_data->buffer_lock);
                core_data->sdev = sdev;
                core_data->id = i;
        }