Merge "Input: synaptics: check input, prevent sysfs races"

This commit is contained in:
Linux Build Service Account 2016-12-01 09:23:49 -08:00 committed by Gerrit - the friendly Code Review server
commit bfaad619ea

View file

@ -358,6 +358,7 @@ static struct device_attribute attrs[] = {
static struct synaptics_rmi4_fwu_handle *fwu; static struct synaptics_rmi4_fwu_handle *fwu;
DECLARE_COMPLETION(fwu_dsx_remove_complete); DECLARE_COMPLETION(fwu_dsx_remove_complete);
DEFINE_MUTEX(dsx_fwu_sysfs_mutex);
static unsigned int extract_uint_le(const unsigned char *ptr) static unsigned int extract_uint_le(const unsigned char *ptr)
{ {
@ -1589,28 +1590,49 @@ static ssize_t fwu_sysfs_show_image(struct file *data_file,
char *buf, loff_t pos, size_t count) char *buf, loff_t pos, size_t count)
{ {
struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
ssize_t retval;
if (!mutex_trylock(&dsx_fwu_sysfs_mutex))
return -EBUSY;
if (count < fwu->config_size) { if (count < fwu->config_size) {
dev_err(rmi4_data->pdev->dev.parent, dev_err(rmi4_data->pdev->dev.parent,
"%s: Not enough space (%zu bytes) in buffer\n", "%s: Not enough space (%zu bytes) in buffer\n",
__func__, count); __func__, count);
return -EINVAL; retval = -EINVAL;
goto show_image_exit;
} }
memcpy(buf, fwu->read_config_buf, fwu->config_size); memcpy(buf, fwu->read_config_buf, fwu->config_size);
retval = fwu->config_size;
return fwu->config_size; show_image_exit:
mutex_unlock(&dsx_fwu_sysfs_mutex);
return retval;
} }
static ssize_t fwu_sysfs_store_image(struct file *data_file, static ssize_t fwu_sysfs_store_image(struct file *data_file,
struct kobject *kobj, struct bin_attribute *attributes, struct kobject *kobj, struct bin_attribute *attributes,
char *buf, loff_t pos, size_t count) char *buf, loff_t pos, size_t count)
{ {
ssize_t retval;
if (!mutex_trylock(&dsx_fwu_sysfs_mutex))
return -EBUSY;
if (count > (fwu->image_size - fwu->data_pos)) { if (count > (fwu->image_size - fwu->data_pos)) {
dev_err(fwu->rmi4_data->pdev->dev.parent, dev_err(fwu->rmi4_data->pdev->dev.parent,
"%s: Not enough space in buffer\n", "%s: Not enough space in buffer\n",
__func__); __func__);
return -EINVAL; retval = -EINVAL;
goto exit;
}
if (!fwu->ext_data_source) {
dev_err(fwu->rmi4_data->pdev->dev.parent,
"%s: Need to set imagesize\n",
__func__);
retval = -EINVAL;
goto exit;
} }
memcpy((void *)(&fwu->ext_data_source[fwu->data_pos]), memcpy((void *)(&fwu->ext_data_source[fwu->data_pos]),
@ -1619,16 +1641,21 @@ static ssize_t fwu_sysfs_store_image(struct file *data_file,
fwu->data_pos += count; fwu->data_pos += count;
exit:
mutex_unlock(&dsx_fwu_sysfs_mutex);
return count; return count;
} }
static ssize_t fwu_sysfs_force_reflash_store(struct device *dev, static ssize_t fwu_sysfs_force_reflash_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count) struct device_attribute *attr, const char *buf, size_t count)
{ {
int retval; ssize_t retval;
unsigned int input; unsigned int input;
struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
if (!mutex_trylock(&dsx_fwu_sysfs_mutex))
return -EBUSY;
if (sscanf(buf, "%u", &input) != 1) { if (sscanf(buf, "%u", &input) != 1) {
retval = -EINVAL; retval = -EINVAL;
goto exit; goto exit;
@ -1657,6 +1684,9 @@ exit:
fwu->ext_data_source = NULL; fwu->ext_data_source = NULL;
fwu->force_update = FORCE_UPDATE; fwu->force_update = FORCE_UPDATE;
fwu->do_lockdown = DO_LOCKDOWN; fwu->do_lockdown = DO_LOCKDOWN;
fwu->data_pos = 0;
fwu->image_size = 0;
mutex_unlock(&dsx_fwu_sysfs_mutex);
return retval; return retval;
} }
@ -1667,6 +1697,9 @@ static ssize_t fwu_sysfs_do_reflash_store(struct device *dev,
unsigned int input; unsigned int input;
struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
if (!mutex_trylock(&dsx_fwu_sysfs_mutex))
return -EBUSY;
if (sscanf(buf, "%u", &input) != 1) { if (sscanf(buf, "%u", &input) != 1) {
retval = -EINVAL; retval = -EINVAL;
goto exit; goto exit;
@ -1700,6 +1733,9 @@ exit:
fwu->ext_data_source = NULL; fwu->ext_data_source = NULL;
fwu->force_update = FORCE_UPDATE; fwu->force_update = FORCE_UPDATE;
fwu->do_lockdown = DO_LOCKDOWN; fwu->do_lockdown = DO_LOCKDOWN;
fwu->data_pos = 0;
fwu->image_size = 0;
mutex_unlock(&dsx_fwu_sysfs_mutex);
return retval; return retval;
} }
@ -1710,6 +1746,9 @@ static ssize_t fwu_sysfs_write_config_store(struct device *dev,
unsigned int input; unsigned int input;
struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
if (!mutex_trylock(&dsx_fwu_sysfs_mutex))
return -EBUSY;
if (sscanf(buf, "%u", &input) != 1) { if (sscanf(buf, "%u", &input) != 1) {
retval = -EINVAL; retval = -EINVAL;
goto exit; goto exit;
@ -1733,6 +1772,9 @@ static ssize_t fwu_sysfs_write_config_store(struct device *dev,
exit: exit:
kfree(fwu->ext_data_source); kfree(fwu->ext_data_source);
fwu->ext_data_source = NULL; fwu->ext_data_source = NULL;
fwu->data_pos = 0;
fwu->image_size = 0;
mutex_unlock(&dsx_fwu_sysfs_mutex);
return retval; return retval;
} }
@ -1749,7 +1791,11 @@ static ssize_t fwu_sysfs_read_config_store(struct device *dev,
if (input != 1) if (input != 1)
return -EINVAL; return -EINVAL;
if (!mutex_trylock(&dsx_fwu_sysfs_mutex))
return -EBUSY;
retval = fwu_do_read_config(); retval = fwu_do_read_config();
mutex_unlock(&dsx_fwu_sysfs_mutex);
if (retval < 0) { if (retval < 0) {
dev_err(rmi4_data->pdev->dev.parent, dev_err(rmi4_data->pdev->dev.parent,
"%s: Failed to read config\n", "%s: Failed to read config\n",
@ -1770,7 +1816,10 @@ static ssize_t fwu_sysfs_config_area_store(struct device *dev,
if (retval) if (retval)
return retval; return retval;
if (!mutex_trylock(&dsx_fwu_sysfs_mutex))
return -EBUSY;
fwu->config_area = config_area; fwu->config_area = config_area;
mutex_unlock(&dsx_fwu_sysfs_mutex);
return count; return count;
} }
@ -1778,17 +1827,30 @@ static ssize_t fwu_sysfs_config_area_store(struct device *dev,
static ssize_t fwu_sysfs_image_name_show(struct device *dev, static ssize_t fwu_sysfs_image_name_show(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
ssize_t retval;
if (!mutex_trylock(&dsx_fwu_sysfs_mutex))
return -EBUSY;
if (strnlen(fwu->rmi4_data->fw_name, SYNA_FW_NAME_MAX_LEN) > 0) if (strnlen(fwu->rmi4_data->fw_name, SYNA_FW_NAME_MAX_LEN) > 0)
return snprintf(buf, PAGE_SIZE, "%s\n", retval = snprintf(buf, PAGE_SIZE, "%s\n",
fwu->rmi4_data->fw_name); fwu->rmi4_data->fw_name);
else else
return snprintf(buf, PAGE_SIZE, "No firmware name given\n"); retval = snprintf(buf, PAGE_SIZE, "No firmware name given\n");
mutex_unlock(&dsx_fwu_sysfs_mutex);
return retval;
} }
static ssize_t fwu_sysfs_image_name_store(struct device *dev, static ssize_t fwu_sysfs_image_name_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count) struct device_attribute *attr, const char *buf, size_t count)
{ {
if (sscanf(buf, "%s", fwu->image_name) != 1) ssize_t retval;
if (!mutex_trylock(&dsx_fwu_sysfs_mutex))
return -EBUSY;
retval = sscanf(buf, "%49s", fwu->image_name);
mutex_unlock(&dsx_fwu_sysfs_mutex);
if (retval != 1)
return -EINVAL; return -EINVAL;
return count; return count;
@ -1801,9 +1863,12 @@ static ssize_t fwu_sysfs_image_size_store(struct device *dev,
unsigned long size; unsigned long size;
struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
if (!mutex_trylock(&dsx_fwu_sysfs_mutex))
return -EBUSY;
retval = sstrtoul(buf, 10, &size); retval = sstrtoul(buf, 10, &size);
if (retval) if (retval)
return retval; goto exit;
fwu->image_size = size; fwu->image_size = size;
fwu->data_pos = 0; fwu->data_pos = 0;
@ -1814,10 +1879,14 @@ static ssize_t fwu_sysfs_image_size_store(struct device *dev,
dev_err(rmi4_data->pdev->dev.parent, dev_err(rmi4_data->pdev->dev.parent,
"%s: Failed to alloc mem for image data\n", "%s: Failed to alloc mem for image data\n",
__func__); __func__);
return -ENOMEM; retval = -ENOMEM;
goto exit;
} }
return count; retval = count;
exit:
mutex_unlock(&dsx_fwu_sysfs_mutex);
return retval;
} }
static ssize_t fwu_sysfs_block_size_show(struct device *dev, static ssize_t fwu_sysfs_block_size_show(struct device *dev,