summary refs log tree commit diff
diff options
context:
space:
mode:
authorKai Vehmanen <kai.vehmanen@linux.intel.com>2022-10-18 15:13:32 +0300
committerMark Brown <broonie@kernel.org>2022-10-18 21:17:21 +0100
commitaf6514f2f3828dc39c96cd4686ef5c9d8368626f (patch)
treee44593d492e3f66bce9ac8133054a7f6d5db7dfa
parentb4dd2e3758709aa8a2abd1ac34c56bd09b980039 (diff)
downloadlinux-af6514f2f3828dc39c96cd4686ef5c9d8368626f.tar.gz
ASoC: SOF: ipc4-mtrace: protect per-core nodes against multiple open
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>
-rw-r--r--sound/soc/sof/ipc4-mtrace.c20
1 files changed, 18 insertions, 2 deletions
diff --git a/sound/soc/sof/ipc4-mtrace.c b/sound/soc/sof/ipc4-mtrace.c
index 9c7080041d08..70dea8ae706e 100644
--- a/sound/soc/sof/ipc4-mtrace.c
+++ b/sound/soc/sof/ipc4-mtrace.c
@@ -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;
 	}