hwmon: Fix a potential race condition on unload
authorJean Delvare <khali@linux-fr.org>
Tue, 12 Jun 2007 11:57:19 +0000 (13:57 +0200)
committerMark M. Hoffman <mhoffman@lightlink.com>
Thu, 19 Jul 2007 18:22:14 +0000 (14:22 -0400)
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>
drivers/hwmon/abituguru.c
drivers/hwmon/f71805f.c
drivers/hwmon/pc87427.c
drivers/hwmon/smsc47m1.c
drivers/hwmon/vt8231.c
drivers/hwmon/w83627hf.c

index bede4d990ea67330546e7b897ae51bf434f55341..11a40da135356984dd4cb1c5d636fcdf8e26f0e7 100644 (file)
@@ -1287,6 +1287,7 @@ abituguru_probe_error:
        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;
 }
@@ -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;
index e8b15047a6d348c8e6072ff4dd8806331372b6fa..8fe4d70d8f51148071df253520a0b00e7d5becd0 100644 (file)
@@ -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);
index 29354fa26f81e3578b7db2dd6b4cc188f4fafff8..2915bc4ad0d566f6a212abff02a9bac71ab52e28 100644 (file)
@@ -484,7 +484,6 @@ 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++) {
@@ -492,6 +491,7 @@ static int __devexit pc87427_remove(struct platform_device *pdev)
                        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);
index 9bac3c2d84f9fbe9ea7b544604758417b8a4aa5f..1de2f2be8708715dcfdf40b191af4ee5db4459d5 100644 (file)
@@ -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);
@@ -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;
index 320d8141be78b3fc923e3e79444401dcca4ef581..c604972f0186ed1013d096bd209b0afa54048bc1 100644 (file)
@@ -743,6 +743,7 @@ exit_remove_files:
        sysfs_remove_group(&pdev->dev.kobj, &vt8231_group);
 
 exit_free:
+       platform_set_drvdata(pdev, NULL);
        kfree(data);
 
 exit_release:
index cd953604c38f372b307c7b70406e827b55086916..1ce78179b0051bc4237af054357a3981fd521838 100644 (file)
@@ -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);
@@ -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);