DivestOS/Patches/Linux_CVEs/CVE-2017-9676/3.0+/0001.patch

273 lines
8.5 KiB
Diff
Raw Normal View History

2017-11-07 21:38:42 -05:00
From d109d8d7e2998a635406215a559e298fa7ef4bb8 Mon Sep 17 00:00:00 2001
From: "lianwei.wang" <lian-wei.wang@motorola.com>
Date: Fri, 30 Mar 2012 12:05:50 +0800
Subject: [PATCH] IKHSS7-18791 msm:fix the list usage in msm_bus_dbg
The list usage in msm_bus_dbg driver are not correct which will cause
kernel panic.
. The list operation should be protected by a lock, e.g. mutex_lock.
. The list entry should only be operated on a valid entry.
Change-Id: I19efeb346d1bacf129ccfd7a6511bc795c029afc
Signed-off-by: Lianwei Wang <lian-wei.wang@motorola.com>
Reviewed-on: http://gerrit.pcs.mot.com/384275
Reviewed-by: Guo-Jian Chen <A21757@motorola.com>
Reviewed-by: Ke Lv <a2435c@motorola.com>
Tested-by: Jira Key <JIRAKEY@motorola.com>
Reviewed-by: Jeffrey Carlyle <jeff.carlyle@motorola.com>
Reviewed-by: Check Patch <CHEKPACH@motorola.com>
Reviewed-by: Klocwork kwcheck <klocwork-kwcheck@sourceforge.mot.com>
Reviewed-by: Tao Hu <taohu@motorola.com>
---
arch/arm/mach-msm/msm_bus/msm_bus_dbg.c | 74 ++++++++++++++++++++++++++-------
1 file changed, 58 insertions(+), 16 deletions(-)
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_dbg.c b/arch/arm/mach-msm/msm_bus/msm_bus_dbg.c
index abd986bca68..76173529d35 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_dbg.c
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_dbg.c
@@ -28,6 +28,7 @@
static struct dentry *clients;
static struct dentry *dir;
static DEFINE_MUTEX(msm_bus_dbg_fablist_lock);
+static DEFINE_MUTEX(msm_bus_dbg_cllist_lock);
struct msm_bus_dbg_state {
uint32_t cl;
uint8_t enable;
@@ -271,16 +272,21 @@ static ssize_t client_data_read(struct file *file, char __user *buf,
size_t count, loff_t *ppos)
{
int bsize = 0;
+ ssize_t read_count = 0;
uint32_t cl = (uint32_t)file->private_data;
struct msm_bus_cldata *cldata = NULL;
+ mutex_lock(&msm_bus_dbg_cllist_lock);
list_for_each_entry(cldata, &cl_list, list) {
- if (cldata->clid == cl)
+ if (cldata->clid == cl) {
+ bsize = cldata->size;
+ read_count = simple_read_from_buffer(buf, count, ppos,
+ cldata->buffer, bsize);
break;
+ }
}
- bsize = cldata->size;
- return simple_read_from_buffer(buf, count, ppos,
- cldata->buffer, bsize);
+ mutex_unlock(&msm_bus_dbg_cllist_lock);
+ return read_count;
}
static int client_data_open(struct inode *inode, struct file *file)
@@ -310,9 +316,11 @@ static int msm_bus_dbg_record_client(const struct msm_bus_scale_pdata *pdata,
{
struct msm_bus_cldata *cldata;
+ mutex_lock(&msm_bus_dbg_cllist_lock);
cldata = kmalloc(sizeof(struct msm_bus_cldata), GFP_KERNEL);
if (!cldata) {
MSM_BUS_DBG("Failed to allocate memory for client data\n");
+ mutex_unlock(&msm_bus_dbg_cllist_lock);
return -ENOMEM;
}
cldata->pdata = pdata;
@@ -321,6 +329,7 @@ static int msm_bus_dbg_record_client(const struct msm_bus_scale_pdata *pdata,
cldata->file = file;
cldata->size = 0;
list_add_tail(&cldata->list, &cl_list);
+ mutex_unlock(&msm_bus_dbg_cllist_lock);
return 0;
}
@@ -328,6 +337,7 @@ static void msm_bus_dbg_free_client(uint32_t clid)
{
struct msm_bus_cldata *cldata = NULL;
+ mutex_lock(&msm_bus_dbg_cllist_lock);
list_for_each_entry(cldata, &cl_list, list) {
if (cldata->clid == clid) {
debugfs_remove(cldata->file);
@@ -336,23 +346,34 @@ static void msm_bus_dbg_free_client(uint32_t clid)
break;
}
}
+ mutex_unlock(&msm_bus_dbg_cllist_lock);
}
static int msm_bus_dbg_fill_cl_buffer(const struct msm_bus_scale_pdata *pdata,
int index, uint32_t clid)
{
- int i = 0, j;
+ int i = 0, j, found = 0;
char *buf = NULL;
struct msm_bus_cldata *cldata = NULL;
struct timespec ts;
+ mutex_lock(&msm_bus_dbg_cllist_lock);
list_for_each_entry(cldata, &cl_list, list) {
- if (cldata->clid == clid)
+ if (cldata->clid == clid) {
+ found = 1;
break;
+ }
+ }
+
+ if (!found) {
+ MSM_BUS_DBG("Client(clid=%d) doesn't exist\n", clid);
+ mutex_unlock(&msm_bus_dbg_cllist_lock);
+ return -EINVAL;
}
if (cldata->file == NULL) {
if (pdata->name == NULL) {
MSM_BUS_DBG("Client doesn't have a name\n");
+ mutex_unlock(&msm_bus_dbg_cllist_lock);
return -EINVAL;
}
cldata->file = msm_bus_dbg_create(pdata->name, S_IRUGO,
@@ -390,6 +411,9 @@ static int msm_bus_dbg_fill_cl_buffer(const struct msm_bus_scale_pdata *pdata,
i += scnprintf(buf + i, MAX_BUFF_SIZE - i, "\n");
cldata->size = i;
+
+ mutex_unlock(&msm_bus_dbg_cllist_lock);
+
return i;
}
@@ -426,6 +450,7 @@ static ssize_t msm_bus_dbg_update_request_write(struct file *file,
chid = buf;
MSM_BUS_DBG("buffer: %s\n size: %d\n", buf, sizeof(ubuf));
+ mutex_lock(&msm_bus_dbg_cllist_lock);
list_for_each_entry(cldata, &cl_list, list) {
if (strstr(chid, cldata->pdata->name)) {
cldata = cldata;
@@ -435,16 +460,19 @@ static ssize_t msm_bus_dbg_update_request_write(struct file *file,
if (ret) {
MSM_BUS_DBG("Index conversion"
" failed\n");
+ mutex_unlock(&msm_bus_dbg_cllist_lock);
return -EFAULT;
}
} else
MSM_BUS_DBG("Error parsing input. Index not"
" found\n");
+ msm_bus_dbg_update_request(cldata, index);
break;
}
}
- msm_bus_dbg_update_request(cldata, index);
+ mutex_unlock(&msm_bus_dbg_cllist_lock);
+
kfree(buf);
return cnt;
}
@@ -458,17 +486,18 @@ static ssize_t fabric_data_read(struct file *file, char __user *buf,
{
struct msm_bus_fab_list *fablist = NULL;
int bsize = 0;
- ssize_t ret;
+ ssize_t ret = 0;
const char *name = file->private_data;
mutex_lock(&msm_bus_dbg_fablist_lock);
list_for_each_entry(fablist, &fabdata_list, list) {
- if (strcmp(fablist->name, name) == 0)
+ if (strcmp(fablist->name, name) == 0) {
+ bsize = fablist->size;
+ ret = simple_read_from_buffer(buf, count, ppos,
+ fablist->buffer, bsize);
break;
+ }
}
- bsize = fablist->size;
- ret = simple_read_from_buffer(buf, count, ppos,
- fablist->buffer, bsize);
mutex_unlock(&msm_bus_dbg_fablist_lock);
return ret;
}
@@ -519,16 +548,25 @@ static int msm_bus_dbg_fill_fab_buffer(const char *fabname,
void *cdata, int nmasters, int nslaves,
int ntslaves)
{
- int i;
+ int i, found = 0;
char *buf = NULL;
struct msm_bus_fab_list *fablist = NULL;
struct timespec ts;
mutex_lock(&msm_bus_dbg_fablist_lock);
list_for_each_entry(fablist, &fabdata_list, list) {
- if (strcmp(fablist->name, fabname) == 0)
+ if (strcmp(fablist->name, fabname) == 0) {
+ found = 1;
break;
+ }
+ }
+
+ if (!found) {
+ MSM_BUS_DBG("Fabric dbg entry %s does not exist, fabname\n");
+ mutex_unlock(&msm_bus_dbg_fablist_lock);
+ return -EINVAL;
}
+
if (fablist->file == NULL) {
MSM_BUS_DBG("Fabric dbg entry does not exist\n");
mutex_unlock(&msm_bus_dbg_fablist_lock);
@@ -542,7 +580,6 @@ static int msm_bus_dbg_fill_fab_buffer(const char *fabname,
fablist->size = 0;
}
buf = fablist->buffer;
- mutex_unlock(&msm_bus_dbg_fablist_lock);
ts = ktime_to_timespec(ktime_get());
i += scnprintf(buf + i, MAX_BUFF_SIZE - i, "\n%d.%d\n",
(int)ts.tv_sec, (int)ts.tv_nsec);
@@ -550,7 +587,6 @@ static int msm_bus_dbg_fill_fab_buffer(const char *fabname,
msm_bus_rpm_fill_cdata_buffer(&i, buf + i, MAX_BUFF_SIZE, cdata,
nmasters, nslaves, ntslaves);
i += scnprintf(buf + i, MAX_BUFF_SIZE - i, "\n");
- mutex_lock(&msm_bus_dbg_fablist_lock);
fablist->size = i;
mutex_unlock(&msm_bus_dbg_fablist_lock);
return 0;
@@ -660,6 +696,7 @@ static int __init msm_bus_debugfs_init(void)
clients, NULL, &msm_bus_dbg_update_request_fops) == NULL)
goto err;
+ mutex_lock(&msm_bus_dbg_cllist_lock);
list_for_each_entry(cldata, &cl_list, list) {
if (cldata->pdata->name == NULL) {
MSM_BUS_DBG("Client name not found\n");
@@ -668,6 +705,7 @@ static int __init msm_bus_debugfs_init(void)
cldata->file = msm_bus_dbg_create(cldata->
pdata->name, S_IRUGO, clients, cldata->clid);
}
+ mutex_unlock(&msm_bus_dbg_cllist_lock);
mutex_lock(&msm_bus_dbg_fablist_lock);
list_for_each_entry(fablist, &fabdata_list, list) {
@@ -675,6 +713,7 @@ static int __init msm_bus_debugfs_init(void)
commit, (void *)fablist->name, &fabric_data_fops);
if (fablist->file == NULL) {
MSM_BUS_DBG("Cannot create files for commit data\n");
+ mutex_unlock(&msm_bus_dbg_fablist_lock);
goto err;
}
}
@@ -694,10 +733,13 @@ static void __exit msm_bus_dbg_teardown(void)
struct msm_bus_cldata *cldata = NULL, *cldata_temp;
debugfs_remove_recursive(dir);
+ mutex_lock(&msm_bus_dbg_cllist_lock);
list_for_each_entry_safe(cldata, cldata_temp, &cl_list, list) {
list_del(&cldata->list);
kfree(cldata);
}
+ mutex_unlock(&msm_bus_dbg_cllist_lock);
+
mutex_lock(&msm_bus_dbg_fablist_lock);
list_for_each_entry_safe(fablist, fablist_temp, &fabdata_list, list) {
list_del(&fablist->list);