From 2ac5dc64f60a3c8829fd2b44ab0a7f320a22c8a9 Mon Sep 17 00:00:00 2001
From: Andrew Chant <achant@google.com>
Date: Tue, 17 Jan 2017 09:26:36 -0800
Subject: [PATCH] input: synaptics: put offset checks under mutex.

Place file offset validity checks under mutex.

BUG: 33555878
BUG: 33002026
Change-Id: I7eae42b9f69bf12114001e2edf752f219edfc56e
Signed-off-by: Andrew Chant <achant@google.com>
---
 .../synaptics_dsx/synaptics_dsx_rmi_dev.c     | 50 ++++++++++++-------
 drivers/input/touchscreen/synaptics_rmi_dev.c | 35 +++++++++----
 2 files changed, 57 insertions(+), 28 deletions(-)

diff --git a/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_rmi_dev.c b/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_rmi_dev.c
index bb9ddd9873cb..a9704af36b2b 100644
--- a/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_rmi_dev.c
+++ b/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_rmi_dev.c
@@ -355,17 +355,24 @@ static ssize_t rmidev_read(struct file *filp, char __user *buf,
 		return -EBADF;
 	}
 
-	if (count == 0)
-		return 0;
+	mutex_lock(&(dev_data->file_mutex));
 
+	if (*f_pos > REG_ADDR_LIMIT) {
+		retval = -EFAULT;
+		goto unlock;
+	}
 	if (count > (REG_ADDR_LIMIT - *f_pos))
 		count = REG_ADDR_LIMIT - *f_pos;
+	if (count == 0) {
+		retval = 0;
+		goto unlock;
+	}
 
 	tmpbuf = kzalloc(count + 1, GFP_KERNEL);
-	if (!tmpbuf)
-		return -ENOMEM;
-
-	mutex_lock(&(dev_data->file_mutex));
+	if (!tmpbuf) {
+		retval = -ENOMEM;
+		goto unlock;
+	}
 
 	retval = synaptics_rmi4_reg_read(rmidev->rmi4_data,
 			*f_pos,
@@ -380,9 +387,10 @@ static ssize_t rmidev_read(struct file *filp, char __user *buf,
 		*f_pos += retval;
 
 clean_up:
+	kfree(tmpbuf);
+unlock:
 	mutex_unlock(&(dev_data->file_mutex));
 
-	kfree(tmpbuf);
 	return retval;
 }
 
@@ -406,32 +414,40 @@ static ssize_t rmidev_write(struct file *filp, const char __user *buf,
 		return -EBADF;
 	}
 
-	if (count == 0)
-		return 0;
+	mutex_lock(&(dev_data->file_mutex));
 
+	if (*f_pos > REG_ADDR_LIMIT) {
+		retval = -EFAULT;
+		goto unlock;
+	}
 	if (count > (REG_ADDR_LIMIT - *f_pos))
 		count = REG_ADDR_LIMIT - *f_pos;
+	if (count == 0) {
+		retval = 0;
+		goto unlock;
+	}
 
 	tmpbuf = kzalloc(count + 1, GFP_KERNEL);
-	if (!tmpbuf)
-		return -ENOMEM;
+	if (!tmpbuf) {
+		retval = -ENOMEM;
+		goto unlock;
+	}
 
 	if (copy_from_user(tmpbuf, buf, count)) {
-		kfree(tmpbuf);
-		return -EFAULT;
+		retval = -EFAULT;
+		goto clean_up;
 	}
 
-	mutex_lock(&(dev_data->file_mutex));
-
 	retval = synaptics_rmi4_reg_write(rmidev->rmi4_data,
 			*f_pos,
 			tmpbuf,
 			count);
 	if (retval >= 0)
 		*f_pos += retval;
-
-	mutex_unlock(&(dev_data->file_mutex));
+clean_up:
 	kfree(tmpbuf);
+unlock:
+	mutex_unlock(&(dev_data->file_mutex));
 	return retval;
 }
 
diff --git a/drivers/input/touchscreen/synaptics_rmi_dev.c b/drivers/input/touchscreen/synaptics_rmi_dev.c
index 88595582579e..4e9812b74879 100644
--- a/drivers/input/touchscreen/synaptics_rmi_dev.c
+++ b/drivers/input/touchscreen/synaptics_rmi_dev.c
@@ -299,13 +299,19 @@ static ssize_t rmidev_read(struct file *filp, char __user *buf,
 		return -EBADF;
 	}
 
-	if (count == 0)
-		return 0;
+	mutex_lock(&(dev_data->file_mutex));
 
+	if (*f_pos > REG_ADDR_LIMIT) {
+		retval = -EFAULT;
+		goto clean_up;
+	}
 	if (count > (REG_ADDR_LIMIT - *f_pos))
 		count = REG_ADDR_LIMIT - *f_pos;
+	if (count == 0) {
+		retval = 0;
+		goto clean_up;
+	}
 
-	mutex_lock(&(dev_data->file_mutex));
 
 	retval = rmidev->fn_ptr->read(rmidev->rmi4_data,
 			*f_pos,
@@ -345,16 +351,23 @@ static ssize_t rmidev_write(struct file *filp, const char __user *buf,
 		return -EBADF;
 	}
 
-	if (count == 0)
-		return 0;
+	mutex_lock(&(dev_data->file_mutex));
 
+	if (*f_pos > REG_ADDR_LIMIT) {
+		retval = -EFAULT;
+		goto clean_up;
+	}
 	if (count > (REG_ADDR_LIMIT - *f_pos))
 		count = REG_ADDR_LIMIT - *f_pos;
+	if (count == 0) {
+		retval = 0;
+		goto clean_up;
+	}
 
-	if (copy_from_user(tmpbuf, buf, count))
-		return -EFAULT;
-
-	mutex_lock(&(dev_data->file_mutex));
+	if (copy_from_user(tmpbuf, buf, count)) {
+		retval = -EFAULT;
+		goto clean_up;
+	}
 
 	retval = rmidev->fn_ptr->write(rmidev->rmi4_data,
 			*f_pos,
@@ -362,7 +375,7 @@ static ssize_t rmidev_write(struct file *filp, const char __user *buf,
 			count);
 	if (retval >= 0)
 		*f_pos += retval;
-
+clean_up:
 	mutex_unlock(&(dev_data->file_mutex));
 
 	return retval;
@@ -503,7 +516,7 @@ static int rmidev_init_device(struct synaptics_rmi4_data *rmi4_data)
 		goto err_rmidev;
 	}
 
-	rmidev->fn_ptr =  kzalloc(sizeof(*(rmidev->fn_ptr)), GFP_KERNEL);
+	rmidev->fn_ptr = kzalloc(sizeof(*(rmidev->fn_ptr)), GFP_KERNEL);
 	if (!rmidev->fn_ptr) {
 		dev_err(&rmi4_data->i2c_client->dev,
 				"%s: Failed to alloc mem for fn_ptr\n",
-- 
GitLab