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

Commit 440cd8b2 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 38917ab0 7c98bebe
Loading
Loading
Loading
Loading
+23 −11
Original line number Diff line number Diff line
/* Copyright (c) 2012, 2016 The Linux Foundation. All rights reserved.
/* Copyright (c) 2012, 2016-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
@@ -744,6 +744,16 @@ static int tmc_enable(struct tmc_drvdata *drvdata, enum tmc_mode mode)
	pm_runtime_get_sync(drvdata->dev);

	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);
		pm_runtime_put(drvdata->dev);
		return -EBUSY;
	}
	spin_unlock_irqrestore(&drvdata->spinlock, flags);

	if (drvdata->config_type == TMC_CONFIG_TYPE_ETR &&
	    drvdata->out_mode == TMC_ETR_OUT_MODE_MEM) {
		/*
@@ -778,17 +788,8 @@ static int tmc_enable(struct tmc_drvdata *drvdata, enum tmc_mode mode)
			return ret;
		}
	}
	mutex_unlock(&drvdata->mem_lock);

	spin_lock_irqsave(&drvdata->spinlock, flags);
	if (drvdata->reading) {
		spin_unlock_irqrestore(&drvdata->spinlock, flags);
		if (drvdata->config_type == TMC_CONFIG_TYPE_ETR
		    && drvdata->out_mode == TMC_ETR_OUT_MODE_USB)
			usb_qdss_close(drvdata->usbch);
		pm_runtime_put(drvdata->dev);
		return -EBUSY;
	}

	if (drvdata->config_type == TMC_CONFIG_TYPE_ETB) {
		tmc_etb_enable_hw(drvdata);
@@ -803,6 +804,7 @@ static int tmc_enable(struct tmc_drvdata *drvdata, enum tmc_mode mode)
	}
	drvdata->enable = true;
	spin_unlock_irqrestore(&drvdata->spinlock, flags);
	mutex_unlock(&drvdata->mem_lock);

	dev_info(drvdata->dev, "TMC enabled\n");
	return 0;
@@ -1046,6 +1048,7 @@ static int tmc_read_prepare(struct tmc_drvdata *drvdata)
	unsigned long flags;
	enum tmc_mode mode;

	mutex_lock(&drvdata->mem_lock);
	spin_lock_irqsave(&drvdata->spinlock, flags);
	if (!drvdata->enable)
		goto out;
@@ -1066,11 +1069,13 @@ static int tmc_read_prepare(struct tmc_drvdata *drvdata)
out:
	drvdata->reading = true;
	spin_unlock_irqrestore(&drvdata->spinlock, flags);
	mutex_unlock(&drvdata->mem_lock);

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

@@ -1245,7 +1250,11 @@ 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 *bufp;

	mutex_lock(&drvdata->mem_lock);

	bufp = drvdata->buf + *ppos;

	if (*ppos + len > drvdata->size)
		len = drvdata->size - *ppos;
@@ -1267,6 +1276,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->mem_lock);
		return -EFAULT;
	}

@@ -1274,6 +1284,8 @@ static ssize_t tmc_read(struct file *file, char __user *data, size_t len,

	dev_dbg(drvdata->dev, "%s: %zu bytes copied, %d bytes left\n",
		__func__, len, (int)(drvdata->size - *ppos));

	mutex_unlock(&drvdata->mem_lock);
	return len;
}