mirror of
https://github.com/Divested-Mobile/DivestOS-Build.git
synced 2024-10-01 01:35:54 -04:00
125 lines
3.7 KiB
Diff
125 lines
3.7 KiB
Diff
|
From 80decd6365deec08c35ecb902a58f9210599b39a Mon Sep 17 00:00:00 2001
|
||
|
From: ansharma <ansharma@codeaurora.org>
|
||
|
Date: Fri, 20 Jan 2017 14:43:57 +0530
|
||
|
Subject: platform: msm: spmi: Fix possible race condition in debugfs
|
||
|
|
||
|
There is a possible race condition when debugfs files are concurrently
|
||
|
accessed by multiple threads. Fix this.
|
||
|
|
||
|
CRs-Fixed: 1106842
|
||
|
Change-Id: Ifd092143f428db3cf73c45ec4f0aaa96318ae165
|
||
|
Signed-off-by: ansharma <ansharma@codeaurora.org>
|
||
|
---
|
||
|
drivers/platform/msm/spmi/spmi-dbgfs.c | 37 +++++++++++++++++++++++++---------
|
||
|
1 file changed, 28 insertions(+), 9 deletions(-)
|
||
|
|
||
|
diff --git a/drivers/platform/msm/spmi/spmi-dbgfs.c b/drivers/platform/msm/spmi/spmi-dbgfs.c
|
||
|
index b0a354b..86f1b0d 100644
|
||
|
--- a/drivers/platform/msm/spmi/spmi-dbgfs.c
|
||
|
+++ b/drivers/platform/msm/spmi/spmi-dbgfs.c
|
||
|
@@ -1,4 +1,4 @@
|
||
|
-/* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.
|
||
|
+/* Copyright (c) 2012-2014, 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
|
||
|
@@ -69,6 +69,7 @@ struct spmi_trans {
|
||
|
u32 addr; /* 20-bit address: SID + PID + Register offset */
|
||
|
u32 offset; /* Offset of last read data */
|
||
|
bool raw_data; /* Set to true for raw data dump */
|
||
|
+ struct mutex spmi_dfs_lock; /* Prevent thread concurrency */
|
||
|
struct spmi_controller *ctrl;
|
||
|
struct spmi_log_buffer *log; /* log buffer */
|
||
|
};
|
||
|
@@ -168,6 +169,7 @@ static int spmi_dfs_open(struct spmi_ctrl_data *ctrl_data, struct file *file)
|
||
|
trans->addr = ctrl_data->addr;
|
||
|
trans->ctrl = ctrl_data->ctrl;
|
||
|
trans->offset = trans->addr;
|
||
|
+ mutex_init(&trans->spmi_dfs_lock);
|
||
|
|
||
|
file->private_data = trans;
|
||
|
return 0;
|
||
|
@@ -197,6 +199,7 @@ static int spmi_dfs_close(struct inode *inode, struct file *file)
|
||
|
|
||
|
if (trans && trans->log) {
|
||
|
file->private_data = NULL;
|
||
|
+ mutex_destroy(&trans->spmi_dfs_lock);
|
||
|
kfree(trans->log);
|
||
|
kfree(trans);
|
||
|
}
|
||
|
@@ -473,14 +476,21 @@ static ssize_t spmi_dfs_reg_write(struct file *file, const char __user *buf,
|
||
|
int cnt = 0;
|
||
|
u8 *values;
|
||
|
size_t ret = 0;
|
||
|
-
|
||
|
+ u32 offset;
|
||
|
+ char *kbuf;
|
||
|
struct spmi_trans *trans = file->private_data;
|
||
|
- u32 offset = trans->offset;
|
||
|
+
|
||
|
+ mutex_lock(&trans->spmi_dfs_lock);
|
||
|
+
|
||
|
+ trans = file->private_data;
|
||
|
+ offset = trans->offset;
|
||
|
|
||
|
/* Make a copy of the user data */
|
||
|
- char *kbuf = kmalloc(count + 1, GFP_KERNEL);
|
||
|
- if (!kbuf)
|
||
|
- return -ENOMEM;
|
||
|
+ kbuf = kmalloc(count + 1, GFP_KERNEL);
|
||
|
+ if (!kbuf) {
|
||
|
+ ret = -ENOMEM;
|
||
|
+ goto unlock_mutex;
|
||
|
+ }
|
||
|
|
||
|
ret = copy_from_user(kbuf, buf, count);
|
||
|
if (ret == count) {
|
||
|
@@ -517,6 +527,8 @@ static ssize_t spmi_dfs_reg_write(struct file *file, const char __user *buf,
|
||
|
|
||
|
free_buf:
|
||
|
kfree(kbuf);
|
||
|
+unlock_mutex:
|
||
|
+ mutex_unlock(&trans->spmi_dfs_lock);
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
@@ -537,10 +549,13 @@ static ssize_t spmi_dfs_reg_read(struct file *file, char __user *buf,
|
||
|
size_t ret;
|
||
|
size_t len;
|
||
|
|
||
|
+ mutex_lock(&trans->spmi_dfs_lock);
|
||
|
/* Is the the log buffer empty */
|
||
|
if (log->rpos >= log->wpos) {
|
||
|
- if (get_log_data(trans) <= 0)
|
||
|
- return 0;
|
||
|
+ if (get_log_data(trans) <= 0) {
|
||
|
+ len = 0;
|
||
|
+ goto unlock_mutex;
|
||
|
+ }
|
||
|
}
|
||
|
|
||
|
len = min(count, log->wpos - log->rpos);
|
||
|
@@ -548,7 +563,8 @@ static ssize_t spmi_dfs_reg_read(struct file *file, char __user *buf,
|
||
|
ret = copy_to_user(buf, &log->data[log->rpos], len);
|
||
|
if (ret == len) {
|
||
|
pr_err("error copy SPMI register values to user\n");
|
||
|
- return -EFAULT;
|
||
|
+ len = -EFAULT;
|
||
|
+ goto unlock_mutex;
|
||
|
}
|
||
|
|
||
|
/* 'ret' is the number of bytes not copied */
|
||
|
@@ -556,6 +572,9 @@ static ssize_t spmi_dfs_reg_read(struct file *file, char __user *buf,
|
||
|
|
||
|
*ppos += len;
|
||
|
log->rpos += len;
|
||
|
+
|
||
|
+unlock_mutex:
|
||
|
+ mutex_unlock(&trans->spmi_dfs_lock);
|
||
|
return len;
|
||
|
}
|
||
|
|
||
|
--
|
||
|
cgit v1.1
|
||
|
|