DivestOS/Patches/Linux_CVEs/CVE-2017-8266/3.10/0001.patch
2017-11-07 21:38:42 -05:00

183 lines
4.9 KiB
Diff

From aa23820b001ab1cfb86b79014e9fc44cd2be9ece Mon Sep 17 00:00:00 2001
From: Ingrid Gallardo <ingridg@codeaurora.org>
Date: Wed, 1 Mar 2017 12:24:06 -0800
Subject: 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 bounderies.
Change-Id: I97a90a154237343d4aaf237c11f525bcc2c3a8e3
Signed-off-by: Ingrid Gallardo <ingridg@codeaurora.org>
Signed-off-by: Nirmal Abraham <nabrah@codeaurora.org>
---
drivers/video/msm/mdss/mdss_debug.c | 48 ++++++++++++++++++++++++++++++-------
1 file changed, 40 insertions(+), 8 deletions(-)
diff --git a/drivers/video/msm/mdss/mdss_debug.c b/drivers/video/msm/mdss/mdss_debug.c
index a95fa43..cedd40cd 100644
--- a/drivers/video/msm/mdss/mdss_debug.c
+++ b/drivers/video/msm/mdss/mdss_debug.c
@@ -1,4 +1,4 @@
-/* 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
@@ -39,6 +39,8 @@
#define PANEL_CMD_MIN_TX_COUNT 2
#define PANEL_DATA_NODE_LEN 80
+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)
@@ -88,8 +90,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);
@@ -109,15 +113,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;
}
@@ -206,11 +216,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)
@@ -251,11 +266,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;
}
@@ -386,8 +403,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);
@@ -407,15 +426,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;
}
@@ -472,6 +497,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;
@@ -483,6 +510,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;
}
@@ -513,17 +541,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;
}
--
cgit v1.1