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

Commit a9a703b2 authored by Raju P.L.S.S.S.N's avatar Raju P.L.S.S.S.N Committed by Naresh Malladi
Browse files

msm: pm: Add mutex lock for shared data



The buffer allocated in file open operations need to be
protected as there can be a possiblity of use-after-free
scenario.

Process A              B
        |              |
      open             |
        |              |
      read started     |
        |             close

Add mutex lock to protect the buffer to avoid this.

Change-Id: I1e066fd0a047bcec2af7829015089d5c882fb2f3
Signed-off-by: default avatarRaju P.L.S.S.S.N <rplsssn@codeaurora.org>
Signed-off-by: default avatarNaresh Malladi <namall@codeaurora.org>
parent 7b1b1d69
Loading
Loading
Loading
Loading
+33 −12
Original line number Diff line number Diff line
/* Copyright (c) 2010-2016, The Linux Foundation. All rights reserved.
/* Copyright (c) 2010-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
@@ -87,6 +87,7 @@ static long *msm_pc_debug_counters;

static cpumask_t retention_cpus;
static DEFINE_SPINLOCK(retention_lock);
static DEFINE_MUTEX(msm_pc_debug_mutex);

static bool msm_pm_is_L1_writeback(void)
{
@@ -678,33 +679,48 @@ static ssize_t msm_pc_debug_counters_file_read(struct file *file,
		char __user *bufu, size_t count, loff_t *ppos)
{
	struct msm_pc_debug_counters_buffer *data;
	ssize_t ret;

	mutex_lock(&msm_pc_debug_mutex);
	data = file->private_data;

	if (!data)
		return -EINVAL;
	if (!data) {
		ret = -EINVAL;
		goto exit;
	}

	if (!bufu)
		return -EINVAL;
	if (!bufu) {
		ret = -EINVAL;
		goto exit;
	}

	if (!access_ok(VERIFY_WRITE, bufu, count))
		return -EFAULT;
	if (!access_ok(VERIFY_WRITE, bufu, count)) {
		ret = -EFAULT;
		goto exit;
	}

	if (*ppos >= data->len && data->len == 0)
		data->len = msm_pc_debug_counters_copy(data);

	return simple_read_from_buffer(bufu, count, ppos,
	ret = simple_read_from_buffer(bufu, count, ppos,
			data->buf, data->len);
exit:
	mutex_unlock(&msm_pc_debug_mutex);
	return ret;
}

static int msm_pc_debug_counters_file_open(struct inode *inode,
		struct file *file)
{
	struct msm_pc_debug_counters_buffer *buf;
	int ret = 0;

	mutex_lock(&msm_pc_debug_mutex);

	if (!inode->i_private)
		return -EINVAL;
	if (!inode->i_private) {
		ret = -EINVAL;
		goto exit;
	}

	file->private_data = kzalloc(
		sizeof(struct msm_pc_debug_counters_buffer), GFP_KERNEL);
@@ -713,19 +729,24 @@ static int msm_pc_debug_counters_file_open(struct inode *inode,
		pr_err("%s: ERROR kmalloc failed to allocate %zu bytes\n",
		__func__, sizeof(struct msm_pc_debug_counters_buffer));

		return -ENOMEM;
		ret = -ENOMEM;
		goto exit;
	}

	buf = file->private_data;
	buf->reg = (long *)inode->i_private;

	return 0;
exit:
	mutex_unlock(&msm_pc_debug_mutex);
	return ret;
}

static int msm_pc_debug_counters_file_close(struct inode *inode,
		struct file *file)
{
	mutex_lock(&msm_pc_debug_mutex);
	kfree(file->private_data);
	mutex_unlock(&msm_pc_debug_mutex);
	return 0;
}