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

Commit 80a39565 authored by Ingrid Gallardo's avatar Ingrid Gallardo Committed by Gerrit - the friendly Code Review server
Browse files

msm: mdss: fix race condition in mdp debugfs



Fix race condition in mdp debugfs properties
during the read and write of the panel and
mdp registers. This race condition can cause
accessing memory out of boundaries.

Change-Id: I97a90a154237343d4aaf237c11f525bcc2c3a8e3
Signed-off-by: default avatarIngrid Gallardo <ingridg@codeaurora.org>
parent d21ab502
Loading
Loading
Loading
Loading
+40 −8
Original line number Diff line number Diff line
/* Copyright (c) 2009-2016, The Linux Foundation. All rights reserved.
/* Copyright (c) 2009-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
@@ -44,6 +44,8 @@

#define INVALID_XIN_ID     0xFF

static DEFINE_MUTEX(mdss_debug_lock);

static char panel_reg[2] = {DEFAULT_READ_PANEL_POWER_MODE_REG, 0x00};

static int panel_debug_base_open(struct inode *inode, struct file *file)
@@ -93,8 +95,10 @@ static ssize_t panel_debug_base_offset_write(struct file *file,
	if (cnt > (dbg->max_offset - off))
		cnt = dbg->max_offset - off;

	mutex_lock(&mdss_debug_lock);
	dbg->off = off;
	dbg->cnt = cnt;
	mutex_unlock(&mdss_debug_lock);

	pr_debug("offset=%x cnt=%d\n", off, cnt);

@@ -114,15 +118,21 @@ static ssize_t panel_debug_base_offset_read(struct file *file,
	if (*ppos)
		return 0;	/* the end */

	mutex_lock(&mdss_debug_lock);
	len = snprintf(buf, sizeof(buf), "0x%02zx %zx\n", dbg->off, dbg->cnt);
	if (len < 0 || len >= sizeof(buf))
	if (len < 0 || len >= sizeof(buf)) {
		mutex_unlock(&mdss_debug_lock);
		return 0;
	}

	if ((count < sizeof(buf)) || copy_to_user(buff, buf, len))
	if ((count < sizeof(buf)) || copy_to_user(buff, buf, len)) {
		mutex_unlock(&mdss_debug_lock);
		return -EFAULT;
	}

	*ppos += len;	/* increase offset */

	mutex_unlock(&mdss_debug_lock);
	return len;
}

@@ -220,11 +230,16 @@ static ssize_t panel_debug_base_reg_read(struct file *file,
	if (!dbg)
		return -ENODEV;

	if (!dbg->cnt)
	mutex_lock(&mdss_debug_lock);
	if (!dbg->cnt) {
		mutex_unlock(&mdss_debug_lock);
		return 0;
	}

	if (*ppos)
	if (*ppos) {
		mutex_unlock(&mdss_debug_lock);
		return 0;	/* the end */
	}

	/* '0x' + 2 digit + blank = 5 bytes for each number */
	reg_buf_len = (dbg->cnt * PANEL_REG_FORMAT_LEN)
@@ -265,11 +280,13 @@ static ssize_t panel_debug_base_reg_read(struct file *file,
	kfree(panel_reg_buf);

	*ppos += len;	/* increase offset */
	mutex_unlock(&mdss_debug_lock);
	return len;

read_reg_fail:
	kfree(rx_buf);
	kfree(panel_reg_buf);
	mutex_unlock(&mdss_debug_lock);
	return rc;
}

@@ -403,8 +420,10 @@ static ssize_t mdss_debug_base_offset_write(struct file *file,
	if (cnt > (dbg->max_offset - off))
		cnt = dbg->max_offset - off;

	mutex_lock(&mdss_debug_lock);
	dbg->off = off;
	dbg->cnt = cnt;
	mutex_unlock(&mdss_debug_lock);

	pr_debug("offset=%x cnt=%x\n", off, cnt);

@@ -424,15 +443,21 @@ static ssize_t mdss_debug_base_offset_read(struct file *file,
	if (*ppos)
		return 0;	/* the end */

	mutex_lock(&mdss_debug_lock);
	len = snprintf(buf, sizeof(buf), "0x%08zx %zx\n", dbg->off, dbg->cnt);
	if (len < 0 || len >= sizeof(buf))
	if (len < 0 || len >= sizeof(buf)) {
		mutex_unlock(&mdss_debug_lock);
		return 0;
	}

	if ((count < sizeof(buf)) || copy_to_user(buff, buf, len))
	if ((count < sizeof(buf)) || copy_to_user(buff, buf, len)) {
		mutex_unlock(&mdss_debug_lock);
		return -EFAULT;
	}

	*ppos += len;	/* increase offset */

	mutex_unlock(&mdss_debug_lock);
	return len;
}

@@ -489,6 +514,8 @@ static ssize_t mdss_debug_base_reg_read(struct file *file,
		return -ENODEV;
	}

	mutex_lock(&mdss_debug_lock);

	if (!dbg->buf) {
		char dump_buf[64];
		char *ptr;
@@ -500,6 +527,7 @@ static ssize_t mdss_debug_base_reg_read(struct file *file,

		if (!dbg->buf) {
			pr_err("not enough memory to hold reg dump\n");
			mutex_unlock(&mdss_debug_lock);
			return -ENOMEM;
		}

@@ -530,17 +558,21 @@ static ssize_t mdss_debug_base_reg_read(struct file *file,
		dbg->buf_len = tot;
	}

	if (*ppos >= dbg->buf_len)
	if (*ppos >= dbg->buf_len) {
		mutex_unlock(&mdss_debug_lock);
		return 0; /* done reading */
	}

	len = min(count, dbg->buf_len - (size_t) *ppos);
	if (copy_to_user(user_buf, dbg->buf + *ppos, len)) {
		pr_err("failed to copy to user\n");
		mutex_unlock(&mdss_debug_lock);
		return -EFAULT;
	}

	*ppos += len; /* increase offset */

	mutex_unlock(&mdss_debug_lock);
	return len;
}