DivestOS/Patches/Linux_CVEs/CVE-2016-10294/0.patch

123 lines
3.5 KiB
Diff

From 9e9bc51ffb8a298f0be5befe346762cdb6e1d49c Mon Sep 17 00:00:00 2001
From: ansharma <ansharma@codeaurora.org>
Date: Wed, 18 Jan 2017 16:46:38 +0530
Subject: power: qpnp-fg: Fix possible race condition in FG debugfs
There is a possible race condition when FG debugfs files are concurrently
accessed by multiple threads. Fix this.
CRs-Fixed: 1105481
Change-Id: I154e7f3cdd8d51cf67ef1dfd9d78f423f183cb64
Signed-off-by: ansharma <ansharma@codeaurora.org>
---
drivers/power/qpnp-fg.c | 34 ++++++++++++++++++++++++++--------
1 file changed, 26 insertions(+), 8 deletions(-)
diff --git a/drivers/power/qpnp-fg.c b/drivers/power/qpnp-fg.c
index 182b562..1e2fefc 100644
--- a/drivers/power/qpnp-fg.c
+++ b/drivers/power/qpnp-fg.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 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
@@ -669,6 +669,7 @@ struct fg_trans {
struct fg_chip *chip;
struct fg_log_buffer *log; /* log buffer */
u8 *data; /* fg data that is read */
+ struct mutex memif_dfs_lock; /* Prevent thread concurrency */
};
struct fg_dbgfs {
@@ -7514,6 +7515,7 @@ static int fg_memif_data_open(struct inode *inode, struct file *file)
trans->addr = dbgfs_data.addr;
trans->chip = dbgfs_data.chip;
trans->offset = trans->addr;
+ mutex_init(&trans->memif_dfs_lock);
file->private_data = trans;
return 0;
@@ -7525,6 +7527,7 @@ static int fg_memif_dfs_close(struct inode *inode, struct file *file)
if (trans && trans->log && trans->data) {
file->private_data = NULL;
+ mutex_destroy(&trans->memif_dfs_lock);
kfree(trans->log);
kfree(trans->data);
kfree(trans);
@@ -7682,10 +7685,13 @@ static ssize_t fg_memif_dfs_reg_read(struct file *file, char __user *buf,
size_t ret;
size_t len;
+ mutex_lock(&trans->memif_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);
@@ -7693,7 +7699,8 @@ static ssize_t fg_memif_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 sram register values to user\n");
- return -EFAULT;
+ len = -EFAULT;
+ goto unlock_mutex;
}
/* 'ret' is the number of bytes not copied */
@@ -7701,6 +7708,9 @@ static ssize_t fg_memif_dfs_reg_read(struct file *file, char __user *buf,
*ppos += len;
log->rpos += len;
+
+unlock_mutex:
+ mutex_unlock(&trans->memif_dfs_lock);
return len;
}
@@ -7721,14 +7731,20 @@ static ssize_t fg_memif_dfs_reg_write(struct file *file, const char __user *buf,
int cnt = 0;
u8 *values;
size_t ret = 0;
+ char *kbuf;
+ u32 offset;
struct fg_trans *trans = file->private_data;
- u32 offset = trans->offset;
+
+ mutex_lock(&trans->memif_dfs_lock);
+ 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) {
@@ -7767,6 +7783,8 @@ static ssize_t fg_memif_dfs_reg_write(struct file *file, const char __user *buf,
free_buf:
kfree(kbuf);
+unlock_mutex:
+ mutex_unlock(&trans->memif_dfs_lock);
return ret;
}
--
cgit v1.1