mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-10 06:09:23 -04:00
coresight-tmc: Re-use ETR buffer across use cases
We can run into use after free scenario for the buffer memory if enable and read operations happen simultaneously. Add mutex protection in order to prevent such a scenario. Change-Id: I3106564a46a9cffc0db8808ba03f78d76c925eca Signed-off-by: Satyajit Desai <sadesai@codeaurora.org> Signed-off-by: Rama Aparna Mallavarapu <aparnam@codeaurora.org> Signed-off-by: Mulu He <muluhe@codeaurora.org> Signed-off-by: Tingwei Zhang <tingwei@codeaurora.org>
This commit is contained in:
parent
c5f22206b8
commit
a8928b2c6d
3 changed files with 21 additions and 4 deletions
|
|
@ -1135,6 +1135,7 @@ static int tmc_enable_etr_sink_sysfs(struct coresight_device *csdev)
|
|||
* buffer, provided the size matches. Any allocation has to be done
|
||||
* with the lock released.
|
||||
*/
|
||||
mutex_lock(&drvdata->mem_lock);
|
||||
spin_lock_irqsave(&drvdata->spinlock, flags);
|
||||
sysfs_buf = READ_ONCE(drvdata->sysfs_buf);
|
||||
if (!sysfs_buf || (sysfs_buf->size != drvdata->size)) {
|
||||
|
|
@ -1142,9 +1143,10 @@ static int tmc_enable_etr_sink_sysfs(struct coresight_device *csdev)
|
|||
|
||||
/* Allocate memory with the locks released */
|
||||
free_buf = new_buf = tmc_etr_setup_sysfs_buf(drvdata);
|
||||
if (IS_ERR(new_buf))
|
||||
if (IS_ERR(new_buf)) {
|
||||
mutex_unlock(&drvdata->mem_lock);
|
||||
return PTR_ERR(new_buf);
|
||||
|
||||
}
|
||||
/* Let's try again */
|
||||
spin_lock_irqsave(&drvdata->spinlock, flags);
|
||||
}
|
||||
|
|
@ -1191,6 +1193,7 @@ out:
|
|||
tmc_etr_free_sysfs_buf(free_buf);
|
||||
|
||||
tmc_etr_byte_cntr_start(drvdata->byte_cntr);
|
||||
mutex_unlock(&drvdata->mem_lock);
|
||||
|
||||
if (!ret)
|
||||
dev_dbg(&csdev->dev, "TMC-ETR enabled\n");
|
||||
|
|
@ -1636,10 +1639,12 @@ static int tmc_disable_etr_sink(struct coresight_device *csdev)
|
|||
unsigned long flags;
|
||||
struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
|
||||
|
||||
mutex_lock(&drvdata->mem_lock);
|
||||
spin_lock_irqsave(&drvdata->spinlock, flags);
|
||||
|
||||
if (drvdata->reading) {
|
||||
spin_unlock_irqrestore(&drvdata->spinlock, flags);
|
||||
mutex_unlock(&drvdata->mem_lock);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
|
|
@ -1667,6 +1672,7 @@ static int tmc_disable_etr_sink(struct coresight_device *csdev)
|
|||
tmc_etr_free_sysfs_buf(drvdata->etr_buf);
|
||||
drvdata->etr_buf = NULL;
|
||||
}
|
||||
mutex_unlock(&drvdata->mem_lock);
|
||||
dev_info(&csdev->dev, "TMC-ETR disabled\n");
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1692,6 +1698,7 @@ int tmc_read_prepare_etr(struct tmc_drvdata *drvdata)
|
|||
if (WARN_ON_ONCE(drvdata->config_type != TMC_CONFIG_TYPE_ETR))
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&drvdata->mem_lock);
|
||||
spin_lock_irqsave(&drvdata->spinlock, flags);
|
||||
if (drvdata->reading) {
|
||||
ret = -EBUSY;
|
||||
|
|
@ -1720,6 +1727,7 @@ int tmc_read_prepare_etr(struct tmc_drvdata *drvdata)
|
|||
drvdata->reading = true;
|
||||
out:
|
||||
spin_unlock_irqrestore(&drvdata->spinlock, flags);
|
||||
mutex_unlock(&drvdata->mem_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -1732,7 +1740,7 @@ int tmc_read_unprepare_etr(struct tmc_drvdata *drvdata)
|
|||
/* config types are set a boot time and never change */
|
||||
if (WARN_ON_ONCE(drvdata->config_type != TMC_CONFIG_TYPE_ETR))
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&drvdata->mem_lock);
|
||||
spin_lock_irqsave(&drvdata->spinlock, flags);
|
||||
|
||||
/* RE-enable the TMC if need be */
|
||||
|
|
@ -1759,5 +1767,7 @@ int tmc_read_unprepare_etr(struct tmc_drvdata *drvdata)
|
|||
if (sysfs_buf)
|
||||
tmc_etr_free_sysfs_buf(sysfs_buf);
|
||||
|
||||
|
||||
mutex_unlock(&drvdata->mem_lock);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -184,19 +184,24 @@ static ssize_t tmc_read(struct file *file, char __user *data, size_t len,
|
|||
ssize_t actual;
|
||||
struct tmc_drvdata *drvdata = container_of(file->private_data,
|
||||
struct tmc_drvdata, miscdev);
|
||||
mutex_lock(&drvdata->mem_lock);
|
||||
actual = tmc_get_sysfs_trace(drvdata, *ppos, len, &bufp);
|
||||
if (actual <= 0)
|
||||
if (actual <= 0) {
|
||||
mutex_unlock(&drvdata->mem_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (copy_to_user(data, bufp, actual)) {
|
||||
dev_dbg(&drvdata->csdev->dev,
|
||||
"%s: copy_to_user failed\n", __func__);
|
||||
mutex_unlock(&drvdata->mem_lock);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
*ppos += actual;
|
||||
dev_dbg(&drvdata->csdev->dev, "%zu bytes copied\n", actual);
|
||||
|
||||
mutex_unlock(&drvdata->mem_lock);
|
||||
return actual;
|
||||
}
|
||||
|
||||
|
|
@ -512,6 +517,7 @@ static int tmc_probe(struct amba_device *adev, const struct amba_id *id)
|
|||
drvdata->base = base;
|
||||
|
||||
spin_lock_init(&drvdata->spinlock);
|
||||
mutex_init(&drvdata->mem_lock);
|
||||
|
||||
devid = readl_relaxed(drvdata->base + CORESIGHT_DEVID);
|
||||
drvdata->config_type = BMVAL(devid, 6, 7);
|
||||
|
|
|
|||
|
|
@ -204,6 +204,7 @@ struct tmc_drvdata {
|
|||
u32 mode;
|
||||
enum tmc_config_type config_type;
|
||||
enum tmc_mem_intf_width memwidth;
|
||||
struct mutex mem_lock;
|
||||
u32 trigger_cntr;
|
||||
u32 etr_caps;
|
||||
struct idr idr;
|
||||
|
|
|
|||
Loading…
Reference in a new issue