Skip to content

Commit

Permalink
hwmon: Fix a potential race condition on unload
Browse files Browse the repository at this point in the history
Fix a potential race condition when some hardware monitoring platform
drivers are being unloaded. I believe that the driver data pointer
shouldn't be cleared before all the sysfs files are removed, otherwise
a sysfs callback might attempt to dereference a NULL pointer. I'm not
sure exactly what the driver core protects drivers against, so let's
play it safe.

While we're here, clear the driver data pointer when probe fails, so
as to not leave an invalid pointer behind us.

Signed-off-by: Jean Delvare <khali@linux-fr.org>
Signed-off-by: Mark M. Hoffman <mhoffman@lightlink.com>
  • Loading branch information
Jean Delvare authored and Mark M. Hoffman committed Jul 19, 2007
1 parent ec5e1a4 commit 04a6217
Show file tree
Hide file tree
Showing 6 changed files with 9 additions and 5 deletions.
3 changes: 2 additions & 1 deletion drivers/hwmon/abituguru.c
Original file line number Diff line number Diff line change
Expand Up @@ -1287,6 +1287,7 @@ static int __devinit abituguru_probe(struct platform_device *pdev)
for (i = 0; i < ARRAY_SIZE(abituguru_sysfs_attr); i++)
device_remove_file(&pdev->dev,
&abituguru_sysfs_attr[i].dev_attr);
platform_set_drvdata(pdev, NULL);
kfree(data);
return res;
}
Expand All @@ -1296,13 +1297,13 @@ static int __devexit abituguru_remove(struct platform_device *pdev)
int i;
struct abituguru_data *data = platform_get_drvdata(pdev);

platform_set_drvdata(pdev, NULL);
hwmon_device_unregister(data->class_dev);
for (i = 0; data->sysfs_attr[i].dev_attr.attr.name; i++)
device_remove_file(&pdev->dev, &data->sysfs_attr[i].dev_attr);
for (i = 0; i < ARRAY_SIZE(abituguru_sysfs_attr); i++)
device_remove_file(&pdev->dev,
&abituguru_sysfs_attr[i].dev_attr);
platform_set_drvdata(pdev, NULL);
kfree(data);

return 0;
Expand Down
2 changes: 1 addition & 1 deletion drivers/hwmon/f71805f.c
Original file line number Diff line number Diff line change
Expand Up @@ -1242,12 +1242,12 @@ static int __devexit f71805f_remove(struct platform_device *pdev)
struct resource *res;
int i;

platform_set_drvdata(pdev, NULL);
hwmon_device_unregister(data->class_dev);
sysfs_remove_group(&pdev->dev.kobj, &f71805f_group);
for (i = 0; i < 4; i++)
sysfs_remove_group(&pdev->dev.kobj, &f71805f_group_optin[i]);
sysfs_remove_group(&pdev->dev.kobj, &f71805f_group_pwm_freq);
platform_set_drvdata(pdev, NULL);
kfree(data);

res = platform_get_resource(pdev, IORESOURCE_IO, 0);
Expand Down
2 changes: 1 addition & 1 deletion drivers/hwmon/pc87427.c
Original file line number Diff line number Diff line change
Expand Up @@ -484,14 +484,14 @@ static int __devexit pc87427_remove(struct platform_device *pdev)
struct resource *res;
int i;

platform_set_drvdata(pdev, NULL);
hwmon_device_unregister(data->class_dev);
device_remove_file(&pdev->dev, &dev_attr_name);
for (i = 0; i < 8; i++) {
if (!(data->fan_enabled & (1 << i)))
continue;
sysfs_remove_group(&pdev->dev.kobj, &pc87427_group_fan[i]);
}
platform_set_drvdata(pdev, NULL);
kfree(data);

res = platform_get_resource(pdev, IORESOURCE_IO, 0);
Expand Down
3 changes: 2 additions & 1 deletion drivers/hwmon/smsc47m1.c
Original file line number Diff line number Diff line change
Expand Up @@ -597,6 +597,7 @@ static int __devinit smsc47m1_probe(struct platform_device *pdev)
error_remove_files:
sysfs_remove_group(&dev->kobj, &smsc47m1_group);
error_free:
platform_set_drvdata(pdev, NULL);
kfree(data);
error_release:
release_region(res->start, SMSC_EXTENT);
Expand All @@ -608,12 +609,12 @@ static int __devexit smsc47m1_remove(struct platform_device *pdev)
struct smsc47m1_data *data = platform_get_drvdata(pdev);
struct resource *res;

platform_set_drvdata(pdev, NULL);
hwmon_device_unregister(data->class_dev);
sysfs_remove_group(&pdev->dev.kobj, &smsc47m1_group);

res = platform_get_resource(pdev, IORESOURCE_IO, 0);
release_region(res->start, SMSC_EXTENT);
platform_set_drvdata(pdev, NULL);
kfree(data);

return 0;
Expand Down
1 change: 1 addition & 0 deletions drivers/hwmon/vt8231.c
Original file line number Diff line number Diff line change
Expand Up @@ -743,6 +743,7 @@ int vt8231_probe(struct platform_device *pdev)
sysfs_remove_group(&pdev->dev.kobj, &vt8231_group);

exit_free:
platform_set_drvdata(pdev, NULL);
kfree(data);

exit_release:
Expand Down
3 changes: 2 additions & 1 deletion drivers/hwmon/w83627hf.c
Original file line number Diff line number Diff line change
Expand Up @@ -1306,6 +1306,7 @@ static int __devinit w83627hf_probe(struct platform_device *pdev)
sysfs_remove_group(&dev->kobj, &w83627hf_group);
sysfs_remove_group(&dev->kobj, &w83627hf_group_opt);
ERROR3:
platform_set_drvdata(pdev, NULL);
kfree(data);
ERROR1:
release_region(res->start, WINB_REGION_SIZE);
Expand All @@ -1318,11 +1319,11 @@ static int __devexit w83627hf_remove(struct platform_device *pdev)
struct w83627hf_data *data = platform_get_drvdata(pdev);
struct resource *res;

platform_set_drvdata(pdev, NULL);
hwmon_device_unregister(data->class_dev);

sysfs_remove_group(&pdev->dev.kobj, &w83627hf_group);
sysfs_remove_group(&pdev->dev.kobj, &w83627hf_group_opt);
platform_set_drvdata(pdev, NULL);
kfree(data);

res = platform_get_resource(pdev, IORESOURCE_IO, 0);
Expand Down

0 comments on commit 04a6217

Please sign in to comment.