Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3f60e22a authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "coresight: tmc: Fix use after free issue with tmc read"

parents 38c95128 324242d9
Loading
Loading
Loading
Loading
+21 −12
Original line number Diff line number Diff line
/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved.
/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -849,6 +849,14 @@ static int tmc_enable(struct tmc_drvdata *drvdata, enum tmc_mode mode)
		return ret;

	mutex_lock(&drvdata->usb_lock);
	spin_lock_irqsave(&drvdata->spinlock, flags);
	if (drvdata->reading) {
		ret = -EBUSY;
		spin_unlock_irqrestore(&drvdata->spinlock, flags);
		goto err0;
	}
	spin_unlock_irqrestore(&drvdata->spinlock, flags);

	if (drvdata->config_type == TMC_CONFIG_TYPE_ETB) {
		coresight_cti_map_trigout(drvdata->cti_flush, 1, 0);
		coresight_cti_map_trigin(drvdata->cti_reset, 2, 0);
@@ -895,10 +903,6 @@ static int tmc_enable(struct tmc_drvdata *drvdata, enum tmc_mode mode)
	}

	spin_lock_irqsave(&drvdata->spinlock, flags);
	if (drvdata->reading) {
		ret = -EBUSY;
		goto err1;
	}

	if (drvdata->config_type == TMC_CONFIG_TYPE_ETB) {
		__tmc_etb_enable(drvdata);
@@ -928,11 +932,6 @@ static int tmc_enable(struct tmc_drvdata *drvdata, enum tmc_mode mode)

	dev_info(drvdata->dev, "TMC enabled\n");
	return 0;
err1:
	spin_unlock_irqrestore(&drvdata->spinlock, flags);
	if (drvdata->config_type == TMC_CONFIG_TYPE_ETR)
		if (drvdata->out_mode == TMC_ETR_OUT_MODE_USB)
			usb_qdss_close(drvdata->usbch);
err0:
	mutex_unlock(&drvdata->usb_lock);
	clk_disable_unprepare(drvdata->clk);
@@ -1327,6 +1326,7 @@ static int tmc_read_prepare(struct tmc_drvdata *drvdata)
	unsigned long flags;
	enum tmc_mode mode;

	mutex_lock(&drvdata->usb_lock);
	spin_lock_irqsave(&drvdata->spinlock, flags);
	if (!drvdata->sticky_enable) {
		dev_err(drvdata->dev, "enable tmc once before reading\n");
@@ -1357,11 +1357,13 @@ static int tmc_read_prepare(struct tmc_drvdata *drvdata)
out:
	drvdata->reading = true;
	spin_unlock_irqrestore(&drvdata->spinlock, flags);
	mutex_unlock(&drvdata->usb_lock);

	dev_info(drvdata->dev, "TMC read start\n");
	return 0;
err:
	spin_unlock_irqrestore(&drvdata->spinlock, flags);
	mutex_unlock(&drvdata->usb_lock);
	return ret;
}

@@ -1543,8 +1545,12 @@ static ssize_t tmc_read(struct file *file, char __user *data, size_t len,
{
	struct tmc_drvdata *drvdata = container_of(file->private_data,
						   struct tmc_drvdata, miscdev);
	char *bufp = drvdata->buf + *ppos;
	char *end = (char *)(drvdata->vaddr + drvdata->size);
	char *bufp, *end;

	mutex_lock(&drvdata->usb_lock);

	bufp  = drvdata->buf + *ppos;
	end = (char *)(drvdata->vaddr + drvdata->size);

	if (*ppos + len > drvdata->size)
		len = drvdata->size - *ppos;
@@ -1571,6 +1577,7 @@ static ssize_t tmc_read(struct file *file, char __user *data, size_t len,

	if (copy_to_user(data, bufp, len)) {
		dev_dbg(drvdata->dev, "%s: copy_to_user failed\n", __func__);
		mutex_unlock(&drvdata->usb_lock);
		return -EFAULT;
	}

@@ -1578,6 +1585,8 @@ static ssize_t tmc_read(struct file *file, char __user *data, size_t len,
out:
	dev_dbg(drvdata->dev, "%s: %zu bytes copied, %d bytes left\n",
		__func__, len, (int) (drvdata->size - *ppos));

	mutex_lock(&drvdata->usb_lock);
	return len;
}