Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 04a6217d authored by Jean Delvare's avatar Jean Delvare Committed by Mark M. Hoffman
Browse files

hwmon: Fix a potential race condition on unload



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: default avatarJean Delvare <khali@linux-fr.org>
Signed-off-by: default avatarMark M. Hoffman <mhoffman@lightlink.com>
parent ec5e1a4b
Loading
Loading
Loading
Loading
+2 −1
Original line number Original line Diff line number Diff line
@@ -1287,6 +1287,7 @@ abituguru_probe_error:
	for (i = 0; i < ARRAY_SIZE(abituguru_sysfs_attr); i++)
	for (i = 0; i < ARRAY_SIZE(abituguru_sysfs_attr); i++)
		device_remove_file(&pdev->dev,
		device_remove_file(&pdev->dev,
			&abituguru_sysfs_attr[i].dev_attr);
			&abituguru_sysfs_attr[i].dev_attr);
	platform_set_drvdata(pdev, NULL);
	kfree(data);
	kfree(data);
	return res;
	return res;
}
}
@@ -1296,13 +1297,13 @@ static int __devexit abituguru_remove(struct platform_device *pdev)
	int i;
	int i;
	struct abituguru_data *data = platform_get_drvdata(pdev);
	struct abituguru_data *data = platform_get_drvdata(pdev);


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


	return 0;
	return 0;
+1 −1
Original line number Original line Diff line number Diff line
@@ -1242,12 +1242,12 @@ static int __devexit f71805f_remove(struct platform_device *pdev)
	struct resource *res;
	struct resource *res;
	int i;
	int i;


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


	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+1 −1
Original line number Original line Diff line number Diff line
@@ -484,7 +484,6 @@ static int __devexit pc87427_remove(struct platform_device *pdev)
	struct resource *res;
	struct resource *res;
	int i;
	int i;


	platform_set_drvdata(pdev, NULL);
	hwmon_device_unregister(data->class_dev);
	hwmon_device_unregister(data->class_dev);
	device_remove_file(&pdev->dev, &dev_attr_name);
	device_remove_file(&pdev->dev, &dev_attr_name);
	for (i = 0; i < 8; i++) {
	for (i = 0; i < 8; i++) {
@@ -492,6 +491,7 @@ static int __devexit pc87427_remove(struct platform_device *pdev)
			continue;
			continue;
		sysfs_remove_group(&pdev->dev.kobj, &pc87427_group_fan[i]);
		sysfs_remove_group(&pdev->dev.kobj, &pc87427_group_fan[i]);
	}
	}
	platform_set_drvdata(pdev, NULL);
	kfree(data);
	kfree(data);


	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+2 −1
Original line number Original line Diff line number Diff line
@@ -597,6 +597,7 @@ static int __devinit smsc47m1_probe(struct platform_device *pdev)
error_remove_files:
error_remove_files:
	sysfs_remove_group(&dev->kobj, &smsc47m1_group);
	sysfs_remove_group(&dev->kobj, &smsc47m1_group);
error_free:
error_free:
	platform_set_drvdata(pdev, NULL);
	kfree(data);
	kfree(data);
error_release:
error_release:
	release_region(res->start, SMSC_EXTENT);
	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 smsc47m1_data *data = platform_get_drvdata(pdev);
	struct resource *res;
	struct resource *res;


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


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


	return 0;
	return 0;
+1 −0
Original line number Original line Diff line number Diff line
@@ -743,6 +743,7 @@ exit_remove_files:
	sysfs_remove_group(&pdev->dev.kobj, &vt8231_group);
	sysfs_remove_group(&pdev->dev.kobj, &vt8231_group);


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


exit_release:
exit_release:
Loading