Commit b0969714 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] request_firmware(): more misc fixes

From: Manuel Estrada Sainz <ranty@ranty.pantax.net>

Based on patch and suggestions from Dmitry Torokhov

- Take advantage of strlcpy.

- Extra error logging.

- Use struct coping instead of memcpy.

- Put all aborting code in a single place, and fully abort if
  fw_realloc_buffer fails.

- Abort on unexpected 'loading' values.
parent 6a2ea2b8
...@@ -34,6 +34,14 @@ struct firmware_priv { ...@@ -34,6 +34,14 @@ struct firmware_priv {
struct timer_list timeout; struct timer_list timeout;
}; };
static inline void
fw_load_abort(struct firmware_priv *fw_priv)
{
fw_priv->abort = 1;
wmb();
complete(&fw_priv->completion);
}
static ssize_t static ssize_t
firmware_timeout_show(struct class *class, char *buf) firmware_timeout_show(struct class *class, char *buf)
{ {
...@@ -113,11 +121,6 @@ firmware_loading_store(struct class_device *class_dev, ...@@ -113,11 +121,6 @@ firmware_loading_store(struct class_device *class_dev,
fw_priv->loading = simple_strtol(buf, NULL, 10); fw_priv->loading = simple_strtol(buf, NULL, 10);
switch (fw_priv->loading) { switch (fw_priv->loading) {
case -1:
fw_priv->abort = 1;
wmb();
complete(&fw_priv->completion);
break;
case 1: case 1:
vfree(fw_priv->fw->data); vfree(fw_priv->fw->data);
fw_priv->fw->data = NULL; fw_priv->fw->data = NULL;
...@@ -125,10 +128,19 @@ firmware_loading_store(struct class_device *class_dev, ...@@ -125,10 +128,19 @@ firmware_loading_store(struct class_device *class_dev,
fw_priv->alloc_size = 0; fw_priv->alloc_size = 0;
break; break;
case 0: case 0:
if (prev_loading == 1) if (prev_loading == 1) {
complete(&fw_priv->completion); complete(&fw_priv->completion);
break; break;
} }
/* fallthrough */
default:
printk(KERN_ERR "%s: unexpected value (%d)\n", __FUNCTION__,
fw_priv->loading);
/* fallthrough */
case -1:
fw_load_abort(fw_priv);
break;
}
return count; return count;
} }
...@@ -164,7 +176,7 @@ fw_realloc_buffer(struct firmware_priv *fw_priv, int min_size) ...@@ -164,7 +176,7 @@ fw_realloc_buffer(struct firmware_priv *fw_priv, int min_size)
if (!new_data) { if (!new_data) {
printk(KERN_ERR "%s: unable to alloc buffer\n", __FUNCTION__); printk(KERN_ERR "%s: unable to alloc buffer\n", __FUNCTION__);
/* Make sure that we don't keep incomplete data */ /* Make sure that we don't keep incomplete data */
fw_priv->abort = 1; fw_load_abort(fw_priv);
return -ENOMEM; return -ENOMEM;
} }
fw_priv->alloc_size += PAGE_SIZE; fw_priv->alloc_size += PAGE_SIZE;
...@@ -221,17 +233,14 @@ static void ...@@ -221,17 +233,14 @@ static void
firmware_class_timeout(u_long data) firmware_class_timeout(u_long data)
{ {
struct firmware_priv *fw_priv = (struct firmware_priv *) data; struct firmware_priv *fw_priv = (struct firmware_priv *) data;
fw_priv->abort = 1; fw_load_abort(fw_priv);
wmb();
complete(&fw_priv->completion);
} }
static inline void static inline void
fw_setup_class_device_id(struct class_device *class_dev, struct device *dev) fw_setup_class_device_id(struct class_device *class_dev, struct device *dev)
{ {
/* XXX warning we should watch out for name collisions */ /* XXX warning we should watch out for name collisions */
strncpy(class_dev->class_id, dev->bus_id, BUS_ID_SIZE); strlcpy(class_dev->class_id, dev->bus_id, BUS_ID_SIZE);
class_dev->class_id[BUS_ID_SIZE - 1] = '\0';
} }
static int static int
fw_setup_class_device(struct class_device **class_dev_p, fw_setup_class_device(struct class_device **class_dev_p,
...@@ -244,6 +253,7 @@ fw_setup_class_device(struct class_device **class_dev_p, ...@@ -244,6 +253,7 @@ fw_setup_class_device(struct class_device **class_dev_p,
GFP_KERNEL); GFP_KERNEL);
if (!fw_priv || !class_dev) { if (!fw_priv || !class_dev) {
printk(KERN_ERR "%s: kmalloc failed\n", __FUNCTION__);
retval = -ENOMEM; retval = -ENOMEM;
goto error_kfree; goto error_kfree;
} }
...@@ -251,12 +261,8 @@ fw_setup_class_device(struct class_device **class_dev_p, ...@@ -251,12 +261,8 @@ fw_setup_class_device(struct class_device **class_dev_p,
memset(class_dev, 0, sizeof (*class_dev)); memset(class_dev, 0, sizeof (*class_dev));
init_completion(&fw_priv->completion); init_completion(&fw_priv->completion);
memcpy(&fw_priv->attr_data, &firmware_attr_data_tmpl, fw_priv->attr_data = firmware_attr_data_tmpl;
sizeof (firmware_attr_data_tmpl)); strlcpy(fw_priv->fw_id, fw_name, FIRMWARE_NAME_MAX);
strncpy(&fw_priv->fw_id[0], fw_name, FIRMWARE_NAME_MAX);
fw_priv->fw_id[FIRMWARE_NAME_MAX - 1] = '\0';
fw_setup_class_device_id(class_dev, device); fw_setup_class_device_id(class_dev, device);
class_dev->dev = device; class_dev->dev = device;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment