diff options
author | Stanislaw W. Gruszka <stf_xl@wp.pl> | 2005-06-28 20:44:51 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-06-28 21:20:30 -0700 |
commit | b92eac01c3c6ad5dab5c74d3bc32ac8e9bf4dae7 (patch) | |
tree | 23d8b84caeee73709f6a6837f773ed4b4be84444 /drivers/base | |
parent | bcc8ca09920755520ba8a1e2d9f72fe8ff892643 (diff) | |
download | lwn-b92eac01c3c6ad5dab5c74d3bc32ac8e9bf4dae7.tar.gz lwn-b92eac01c3c6ad5dab5c74d3bc32ac8e9bf4dae7.zip |
[PATCH] request_firmware(): avoid race conditions
Avoid race occurs when some process have open file descriptor for class
device attributes and already firmware allocated memory are freed. Don't
allow negative loading timeout.
Signed-off-by: Stanislaw W. Gruszka <stf_xl@wp.pl>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers/base')
-rw-r--r-- | drivers/base/firmware_class.c | 13 |
1 files changed, 10 insertions, 3 deletions
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index 97fe13f7f07c..652281402c92 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c @@ -74,6 +74,8 @@ static ssize_t firmware_timeout_store(struct class *class, const char *buf, size_t count) { loading_timeout = simple_strtol(buf, NULL, 10); + if (loading_timeout < 0) + loading_timeout = 0; return count; } @@ -138,6 +140,10 @@ firmware_loading_store(struct class_device *class_dev, switch (loading) { case 1: down(&fw_lock); + if (!fw_priv->fw) { + up(&fw_lock); + break; + } vfree(fw_priv->fw->data); fw_priv->fw->data = NULL; fw_priv->fw->size = 0; @@ -178,7 +184,7 @@ firmware_data_read(struct kobject *kobj, down(&fw_lock); fw = fw_priv->fw; - if (test_bit(FW_STATUS_DONE, &fw_priv->status)) { + if (!fw || test_bit(FW_STATUS_DONE, &fw_priv->status)) { ret_count = -ENODEV; goto out; } @@ -238,9 +244,10 @@ firmware_data_write(struct kobject *kobj, if (!capable(CAP_SYS_RAWIO)) return -EPERM; + down(&fw_lock); fw = fw_priv->fw; - if (test_bit(FW_STATUS_DONE, &fw_priv->status)) { + if (!fw || test_bit(FW_STATUS_DONE, &fw_priv->status)) { retval = -ENODEV; goto out; } @@ -418,7 +425,7 @@ request_firmware(const struct firmware **firmware_p, const char *name, fw_priv = class_get_devdata(class_dev); - if (loading_timeout) { + if (loading_timeout > 0) { fw_priv->timeout.expires = jiffies + loading_timeout * HZ; add_timer(&fw_priv->timeout); } |