[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>

authored by Stanislaw W. Gruszka and committed by Linus Torvalds b92eac01 bcc8ca09

+10 -3
+10 -3
drivers/base/firmware_class.c
··· 74 firmware_timeout_store(struct class *class, const char *buf, size_t count) 75 { 76 loading_timeout = simple_strtol(buf, NULL, 10); 77 return count; 78 } 79 ··· 140 switch (loading) { 141 case 1: 142 down(&fw_lock); 143 vfree(fw_priv->fw->data); 144 fw_priv->fw->data = NULL; 145 fw_priv->fw->size = 0; ··· 184 185 down(&fw_lock); 186 fw = fw_priv->fw; 187 - if (test_bit(FW_STATUS_DONE, &fw_priv->status)) { 188 ret_count = -ENODEV; 189 goto out; 190 } ··· 244 245 if (!capable(CAP_SYS_RAWIO)) 246 return -EPERM; 247 down(&fw_lock); 248 fw = fw_priv->fw; 249 - if (test_bit(FW_STATUS_DONE, &fw_priv->status)) { 250 retval = -ENODEV; 251 goto out; 252 } ··· 425 426 fw_priv = class_get_devdata(class_dev); 427 428 - if (loading_timeout) { 429 fw_priv->timeout.expires = jiffies + loading_timeout * HZ; 430 add_timer(&fw_priv->timeout); 431 }
··· 74 firmware_timeout_store(struct class *class, const char *buf, size_t count) 75 { 76 loading_timeout = simple_strtol(buf, NULL, 10); 77 + if (loading_timeout < 0) 78 + loading_timeout = 0; 79 return count; 80 } 81 ··· 138 switch (loading) { 139 case 1: 140 down(&fw_lock); 141 + if (!fw_priv->fw) { 142 + up(&fw_lock); 143 + break; 144 + } 145 vfree(fw_priv->fw->data); 146 fw_priv->fw->data = NULL; 147 fw_priv->fw->size = 0; ··· 178 179 down(&fw_lock); 180 fw = fw_priv->fw; 181 + if (!fw || test_bit(FW_STATUS_DONE, &fw_priv->status)) { 182 ret_count = -ENODEV; 183 goto out; 184 } ··· 238 239 if (!capable(CAP_SYS_RAWIO)) 240 return -EPERM; 241 + 242 down(&fw_lock); 243 fw = fw_priv->fw; 244 + if (!fw || test_bit(FW_STATUS_DONE, &fw_priv->status)) { 245 retval = -ENODEV; 246 goto out; 247 } ··· 418 419 fw_priv = class_get_devdata(class_dev); 420 421 + if (loading_timeout > 0) { 422 fw_priv->timeout.expires = jiffies + loading_timeout * HZ; 423 add_timer(&fw_priv->timeout); 424 }