Update Linux CVE patches

This commit is contained in:
Tad 2017-10-29 22:14:37 -04:00
parent 12b63c12b7
commit 3989a1b20b
958 changed files with 21074 additions and 397 deletions

View file

@ -0,0 +1,444 @@
From 9397e20764da2fdffdfe20e35cb78211753b83cc Mon Sep 17 00:00:00 2001
From: Andrew Chant <achant@google.com>
Date: Wed, 14 Sep 2016 17:21:48 -0700
Subject: [PATCH] input: synaptics: prevent sysfs races
concurrent sysfs calls on the fw updater can cause
ugly race conditions. Return EBUSY on concurrent sysfs calls.
For sysfs calls which generate deferred work, prevent
the deferred work from running concurrently with other
sysfs calls.
Change-Id: Ie33add946fbcca8309998e4cb7cb01525c667c7e
Signed-off-by: Andrew Chant <achant@google.com>
Bug: 31252388
---
drivers/input/touchscreen/synaptics_fw_update.c | 144 ++++++++++++++++++------
1 file changed, 109 insertions(+), 35 deletions(-)
diff --git a/drivers/input/touchscreen/synaptics_fw_update.c b/drivers/input/touchscreen/synaptics_fw_update.c
index 79b3a780550b8..ffa992b829a5a 100644
--- a/drivers/input/touchscreen/synaptics_fw_update.c
+++ b/drivers/input/touchscreen/synaptics_fw_update.c
@@ -22,6 +22,7 @@
#include <linux/slab.h>
#include <linux/i2c.h>
#include <linux/interrupt.h>
+#include <linux/mutex.h>
#include <linux/delay.h>
#include <linux/input.h>
#include <linux/firmware.h>
@@ -296,6 +297,7 @@ struct synaptics_rmi4_fwu_handle {
static struct synaptics_rmi4_fwu_handle *fwu;
DECLARE_COMPLETION(fwu_remove_complete);
+DEFINE_MUTEX(fwu_sysfs_mutex);
static unsigned int extract_uint(const unsigned char *ptr)
{
@@ -1713,34 +1715,47 @@ static ssize_t fwu_sysfs_show_image(struct file *data_file,
char *buf, loff_t pos, size_t count)
{
struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
+ ssize_t retval;
+
+ if (!mutex_trylock(&fwu_sysfs_mutex))
+ return -EBUSY;
if (count < fwu->config_size) {
dev_err(&rmi4_data->i2c_client->dev,
"%s: Not enough space (%zu bytes) in buffer\n",
__func__, count);
- return -EINVAL;
+ retval = -EINVAL;
+ goto show_image_exit;
}
memcpy(buf, fwu->read_config_buf, fwu->config_size);
-
- return fwu->config_size;
+ retval = fwu->config_size;
+show_image_exit:
+ mutex_unlock(&fwu_sysfs_mutex);
+ return retval;
}
static ssize_t fwu_sysfs_store_image(struct file *data_file,
struct kobject *kobj, struct bin_attribute *attributes,
char *buf, loff_t pos, size_t count)
{
+ ssize_t retval;
+ if (!mutex_trylock(&fwu_sysfs_mutex))
+ return -EBUSY;
+
if (!fwu->ext_data_source) {
dev_err(&fwu->rmi4_data->i2c_client->dev,
"Cannot use this without setting imagesize!\n");
- return -EAGAIN;
+ retval = -EAGAIN;
+ goto store_image_exit;
}
if (count > fwu->image_size - fwu->data_pos) {
dev_err(&fwu->rmi4_data->i2c_client->dev,
"%s: Not enough space in buffer\n",
__func__);
- return -EINVAL;
+ retval = -EINVAL;
+ goto store_image_exit;
}
memcpy((void *)(&fwu->ext_data_source[fwu->data_pos]),
@@ -1749,8 +1764,11 @@ static ssize_t fwu_sysfs_store_image(struct file *data_file,
fwu->data_buffer = fwu->ext_data_source;
fwu->data_pos += count;
+ retval = count;
- return count;
+store_image_exit:
+ mutex_unlock(&fwu_sysfs_mutex);
+ return retval;
}
static ssize_t fwu_sysfs_image_name_store(struct device *dev,
@@ -1758,11 +1776,15 @@ static ssize_t fwu_sysfs_image_name_store(struct device *dev,
{
struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
char *strptr;
+ ssize_t retval;
+ if (!mutex_trylock(&fwu_sysfs_mutex))
+ return -EBUSY;
if (count >= NAME_BUFFER_SIZE) {
dev_err(&rmi4_data->i2c_client->dev,
"Input over %d characters long\n", NAME_BUFFER_SIZE);
- return -EINVAL;
+ retval = -EINVAL;
+ goto image_name_store_exit;
}
strptr = strnstr(buf, ".img",
@@ -1770,21 +1792,32 @@ static ssize_t fwu_sysfs_image_name_store(struct device *dev,
if (!strptr) {
dev_err(&rmi4_data->i2c_client->dev,
"Input is not valid .img file\n");
- return -EINVAL;
+ retval = -EINVAL;
+ goto image_name_store_exit;
}
strlcpy(rmi4_data->fw_image_name, buf, count);
- return count;
+ retval = count;
+
+image_name_store_exit:
+ mutex_unlock(&fwu_sysfs_mutex);
+ return retval;
}
static ssize_t fwu_sysfs_image_name_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
+ ssize_t retval;
+ if (!mutex_trylock(&fwu_sysfs_mutex))
+ return -EBUSY;
if (strnlen(fwu->rmi4_data->fw_image_name, NAME_BUFFER_SIZE) > 0)
- return snprintf(buf, PAGE_SIZE, "%s\n",
+ retval = snprintf(buf, PAGE_SIZE, "%s\n",
fwu->rmi4_data->fw_image_name);
else
- return snprintf(buf, PAGE_SIZE, "No firmware name given\n");
+ retval = snprintf(buf, PAGE_SIZE, "No firmware name given\n");
+
+ mutex_unlock(&fwu_sysfs_mutex);
+ return retval;
}
static ssize_t fwu_sysfs_force_reflash_store(struct device *dev,
@@ -1794,14 +1827,17 @@ static ssize_t fwu_sysfs_force_reflash_store(struct device *dev,
unsigned int input;
struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
+ if (!mutex_trylock(&fwu_sysfs_mutex))
+ return -EBUSY;
+
if (sscanf(buf, "%u", &input) != 1) {
retval = -EINVAL;
- goto exit;
+ goto force_reflash_store_exit;
}
if (input != 1) {
retval = -EINVAL;
- goto exit;
+ goto force_reflash_store_exit;
}
if (LOCKDOWN)
fwu->do_lockdown = true;
@@ -1812,16 +1848,18 @@ static ssize_t fwu_sysfs_force_reflash_store(struct device *dev,
dev_err(&rmi4_data->i2c_client->dev,
"%s: Failed to do reflash\n",
__func__);
- goto exit;
+ goto force_reflash_store_free_exit;
}
retval = count;
-exit:
+force_reflash_store_free_exit:
kfree(fwu->ext_data_source);
fwu->ext_data_source = NULL;
fwu->force_update = FORCE_UPDATE;
fwu->do_lockdown = rmi4_data->board->do_lockdown;
+force_reflash_store_exit:
+ mutex_unlock(&fwu_sysfs_mutex);
return retval;
}
@@ -1832,9 +1870,12 @@ static ssize_t fwu_sysfs_do_reflash_store(struct device *dev,
unsigned int input;
struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
+ if (!mutex_trylock(&fwu_sysfs_mutex))
+ return -EBUSY;
+
if (sscanf(buf, "%u", &input) != 1) {
retval = -EINVAL;
- goto exit;
+ goto reflash_store_exit;
}
if (input & LOCKDOWN) {
@@ -1844,7 +1885,7 @@ static ssize_t fwu_sysfs_do_reflash_store(struct device *dev,
if ((input != NORMAL) && (input != FORCE)) {
retval = -EINVAL;
- goto exit;
+ goto reflash_store_exit;
}
if (input == FORCE)
@@ -1855,16 +1896,18 @@ static ssize_t fwu_sysfs_do_reflash_store(struct device *dev,
dev_err(&rmi4_data->i2c_client->dev,
"%s: Failed to do reflash\n",
__func__);
- goto exit;
+ goto reflash_store_free_exit;
}
retval = count;
-exit:
+reflash_store_free_exit:
kfree(fwu->ext_data_source);
fwu->ext_data_source = NULL;
fwu->force_update = FORCE_UPDATE;
fwu->do_lockdown = rmi4_data->board->do_lockdown;
+reflash_store_exit:
+ mutex_unlock(&fwu_sysfs_mutex);
return retval;
}
@@ -1875,26 +1918,31 @@ static ssize_t fwu_sysfs_write_lockdown_store(struct device *dev,
unsigned int input;
struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
+ if (!mutex_trylock(&fwu_sysfs_mutex))
+ return -EBUSY;
+
if (sscanf(buf, "%u", &input) != 1) {
retval = -EINVAL;
- goto exit;
+ goto lockdown_store_exit;
}
if (input != 1) {
retval = -EINVAL;
- goto exit;
+ goto lockdown_store_exit;
}
if (!fwu->ext_data_source) {
dev_err(&fwu->rmi4_data->i2c_client->dev,
"Cannot use this without loading image in manual way!\n");
- return -EAGAIN;
+ retval = -EAGAIN;
+ goto lockdown_store_exit;
}
if (fwu->rmi4_data->suspended == true) {
dev_err(&fwu->rmi4_data->i2c_client->dev,
"Cannot lockdown while device is in suspend\n");
- return -EBUSY;
+ retval = -EBUSY;
+ goto lockdown_store_exit;
}
retval = fwu_start_write_lockdown();
@@ -1902,16 +1950,18 @@ static ssize_t fwu_sysfs_write_lockdown_store(struct device *dev,
dev_err(&rmi4_data->i2c_client->dev,
"%s: Failed to write lockdown block\n",
__func__);
- goto exit;
+ goto lockdown_store_free_exit;
}
retval = count;
-exit:
+lockdown_store_free_exit:
kfree(fwu->ext_data_source);
fwu->ext_data_source = NULL;
fwu->force_update = FORCE_UPDATE;
fwu->do_lockdown = rmi4_data->board->do_lockdown;
+lockdown_store_exit:
+ mutex_unlock(&fwu_sysfs_mutex);
return retval;
}
@@ -1920,6 +1970,8 @@ static ssize_t fwu_sysfs_check_fw_store(struct device *dev,
{
unsigned int input = 0;
+ /* Takes fwu_sysfs_mutex in the deferred work function. */
+
if (sscanf(buf, "%u", &input) != 1)
return -EINVAL;
@@ -1942,26 +1994,31 @@ static ssize_t fwu_sysfs_write_config_store(struct device *dev,
unsigned int input;
struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
+ if (!mutex_trylock(&fwu_sysfs_mutex))
+ return -EBUSY;
+
if (sscanf(buf, "%u", &input) != 1) {
retval = -EINVAL;
- goto exit;
+ goto write_config_store_exit;
}
if (input != 1) {
retval = -EINVAL;
- goto exit;
+ goto write_config_store_exit;
}
if (!fwu->ext_data_source) {
dev_err(&fwu->rmi4_data->i2c_client->dev,
"Cannot use this without loading image in manual way!\n");
- return -EAGAIN;
+ retval = -EAGAIN;
+ goto write_config_store_exit;
}
if (fwu->rmi4_data->suspended == true) {
dev_err(&fwu->rmi4_data->i2c_client->dev,
"Cannot write config while device is in suspend\n");
- return -EBUSY;
+ retval = -EBUSY;
+ goto write_config_store_exit;
}
retval = fwu_start_write_config();
@@ -1969,14 +2026,16 @@ static ssize_t fwu_sysfs_write_config_store(struct device *dev,
dev_err(&rmi4_data->i2c_client->dev,
"%s: Failed to write config\n",
__func__);
- goto exit;
+ goto write_config_store_free_exit;
}
retval = count;
-exit:
+write_config_store_free_exit:
kfree(fwu->ext_data_source);
fwu->ext_data_source = NULL;
+write_config_store_exit:
+ mutex_unlock(&fwu_sysfs_mutex);
return retval;
}
@@ -1999,7 +2058,11 @@ static ssize_t fwu_sysfs_read_config_store(struct device *dev,
return -EBUSY;
}
+ if (!mutex_trylock(&fwu_sysfs_mutex))
+ return -EBUSY;
retval = fwu_do_read_config();
+ mutex_unlock(&fwu_sysfs_mutex);
+
if (retval < 0) {
dev_err(&rmi4_data->i2c_client->dev,
"%s: Failed to read config\n",
@@ -2028,7 +2091,10 @@ static ssize_t fwu_sysfs_config_area_store(struct device *dev,
return -EINVAL;
}
+ if (!mutex_trylock(&fwu_sysfs_mutex))
+ return -EBUSY;
fwu->config_area = config_area;
+ mutex_unlock(&fwu_sysfs_mutex);
return count;
}
@@ -2039,10 +2105,12 @@ static ssize_t fwu_sysfs_image_size_store(struct device *dev,
int retval;
unsigned long size;
struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
+ if (!mutex_trylock(&fwu_sysfs_mutex))
+ return -EBUSY;
retval = kstrtoul(buf, 10, &size);
if (retval)
- return retval;
+ goto image_size_store_exit;
fwu->image_size = size;
fwu->data_pos = 0;
@@ -2053,10 +2121,12 @@ static ssize_t fwu_sysfs_image_size_store(struct device *dev,
dev_err(&rmi4_data->i2c_client->dev,
"%s: Failed to alloc mem for image data\n",
__func__);
- return -ENOMEM;
+ retval = -ENOMEM;
}
- return count;
+image_size_store_exit:
+ mutex_unlock(&fwu_sysfs_mutex);
+ return retval;
}
static ssize_t fwu_sysfs_block_size_show(struct device *dev,
@@ -2241,6 +2311,8 @@ static void synaptics_rmi4_fwu_work(struct work_struct *work)
container_of(to_delayed_work(work),
struct synaptics_rmi4_fwu_handle, fwu_work);
+ mutex_lock(&fwu_sysfs_mutex);
+
if (fwu->fn_ptr->enable)
fwu->fn_ptr->enable(fwu->rmi4_data, false);
@@ -2248,6 +2320,8 @@ static void synaptics_rmi4_fwu_work(struct work_struct *work)
if (fwu->fn_ptr->enable)
fwu->fn_ptr->enable(fwu->rmi4_data, true);
+
+ mutex_unlock(&fwu_sysfs_mutex);
}
static int synaptics_rmi4_fwu_init(struct synaptics_rmi4_data *rmi4_data)
@@ -2338,7 +2412,7 @@ static int synaptics_rmi4_fwu_init(struct synaptics_rmi4_data *rmi4_data)
INIT_DELAYED_WORK(&fwu->fwu_work, synaptics_rmi4_fwu_work);
#endif
- retval = sysfs_create_bin_file(&rmi4_data->i2c_client->dev.kobj,
+ retval = sysfs_create_bin_file(&rmi4_data->i2c_client->dev.kobj,
&dev_attr_data);
if (retval < 0) {
dev_err(&rmi4_data->i2c_client->dev,

View file

@ -0,0 +1,61 @@
From fd11eb5c433743c87bebe699604adfd7e7e805cf Mon Sep 17 00:00:00 2001
From: Min Chong <mchong@google.com>
Date: Thu, 13 Oct 2016 09:47:01 -0700
Subject: [PATCH] input: synaptics_dsx: add bounds checks for firmware id
A series of characters between '0' and '9' with a length more than
MAX_FIRMWARE_ID_LEN causes a heap buffer overflow. This is
mitigated by performing a bounds check.
Bug: 31911920
Signed-off-by: Mark Salyzyn <salyzyn@google.com>
Signed-off-by: Min Chong <mchong@google.com>
Change-Id: Iaefe92df2610153f2d3e2caa58322ae82cb5b7c2
---
.../touchscreen/synaptics_dsx25/synaptics_dsx_fw_update.c | 13 +++++++++----
1 file changed, 9 insertions(+), 4 deletions(-)
diff --git a/drivers/input/touchscreen/synaptics_dsx25/synaptics_dsx_fw_update.c b/drivers/input/touchscreen/synaptics_dsx25/synaptics_dsx_fw_update.c
index 908693bd26a43..ff82a4f3a55e8 100755
--- a/drivers/input/touchscreen/synaptics_dsx25/synaptics_dsx_fw_update.c
+++ b/drivers/input/touchscreen/synaptics_dsx25/synaptics_dsx_fw_update.c
@@ -16,6 +16,7 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
+#include <linux/ctype.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
@@ -2154,15 +2155,15 @@ static int fwu_read_f34_blocks(unsigned short block_cnt, unsigned char cmd)
static int fwu_get_image_firmware_id(unsigned int *fw_id)
{
int retval;
- unsigned char index = 0;
- char *strptr;
char *firmware_id;
struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
if (fwu->img.contains_firmware_id) {
*fw_id = fwu->img.firmware_id;
} else {
- strptr = strnstr(fwu->image_name, "PR", MAX_IMAGE_NAME_LEN);
+ size_t index, max_index;
+ unsigned char *strptr = strnstr(fwu->image_name, "PR", MAX_IMAGE_NAME_LEN);
+
if (!strptr) {
dev_err(rmi4_data->pdev->dev.parent,
"%s: No valid PR number (PRxxxxxxx) "
@@ -2179,7 +2180,11 @@ static int fwu_get_image_firmware_id(unsigned int *fw_id)
__func__);
return -ENOMEM;
}
- while (strptr[index] >= '0' && strptr[index] <= '9') {
+
+ max_index = min((ptrdiff_t)(MAX_FIRMWARE_ID_LEN - 1),
+ &fwu->image_name[MAX_IMAGE_NAME_LEN] - strptr);
+ index = 0;
+ while (index < max_index && isdigit(strptr[index])) {
firmware_id[index] = strptr[index];
index++;
}

View file

@ -0,0 +1,62 @@
From 8a950b2d64cec7b8022b7572c2d3d9221b2dbab2 Mon Sep 17 00:00:00 2001
From: Min Chong <mchong@google.com>
Date: Thu, 13 Oct 2016 09:53:23 -0700
Subject: [PATCH] input: synaptics_dsx: add bounds checks for firmware id
A series of characters between '0' and '9' with a length more than
MAX_FIRMWARE_ID_LEN causes a heap buffer overflow. This is
mitigated by performing a bounds check.
Bug: 31911920
Signed-off-by: Mark Salyzyn <salyzyn@google.com>
Signed-off-by: Min Chong <mchong@google.com>
Change-Id: Iaefe92df2610153f2d3e2caa58322ae82cb5b7c2
---
.../synaptics_dsx_htc_2.6/synaptics_dsx_fw_update.c | 14 +++++++++-----
1 file changed, 9 insertions(+), 5 deletions(-)
diff --git a/drivers/input/touchscreen/synaptics_dsx_htc_2.6/synaptics_dsx_fw_update.c b/drivers/input/touchscreen/synaptics_dsx_htc_2.6/synaptics_dsx_fw_update.c
index af6f92553aa7e..05f13b427739b 100644
--- a/drivers/input/touchscreen/synaptics_dsx_htc_2.6/synaptics_dsx_fw_update.c
+++ b/drivers/input/touchscreen/synaptics_dsx_htc_2.6/synaptics_dsx_fw_update.c
@@ -30,7 +30,7 @@
* TOTAL CUMULATIVE LIABILITY TO ANY PARTY SHALL NOT EXCEED ONE HUNDRED U.S.
* DOLLARS.
*/
-
+#include <linux/ctype.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
@@ -2508,15 +2508,15 @@ static int fwu_read_f34_blocks(unsigned short block_cnt, unsigned char cmd)
static int fwu_get_image_firmware_id(unsigned int *fw_id)
{
int retval;
- unsigned char index = 0;
- char *strptr;
char *firmware_id;
struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
if (fwu->img.contains_firmware_id) {
*fw_id = fwu->img.firmware_id;
} else {
- strptr = strnstr(fwu->image_name, "PR", MAX_IMAGE_NAME_LEN);
+ size_t index, max_index;
+ unsigned char *strptr = strnstr(fwu->image_name, "PR", MAX_IMAGE_NAME_LEN);
+
if (!strptr) {
dev_err(rmi4_data->pdev->dev.parent,
"%s: No valid PR number (PRxxxxxxx) found in image file name (%s)\n",
@@ -2532,7 +2532,11 @@ static int fwu_get_image_firmware_id(unsigned int *fw_id)
__func__);
return -ENOMEM;
}
- while (strptr[index] >= '0' && strptr[index] <= '9') {
+
+ max_index = min((ptrdiff_t)(MAX_FIRMWARE_ID_LEN - 1),
+ &fwu->image_name[MAX_IMAGE_NAME_LEN] - strptr);
+ index = 0;
+ while (index < max_index && isdigit(strptr[index])) {
firmware_id[index] = strptr[index];
index++;
}