From 9d3ab801740ab5ff1e22932fdfecdaacd0d64a18 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sat, 24 Aug 2013 10:27:29 -0700 Subject: [PATCH] staging: android: timed_output: fix sysfs file creation race The sysfs file for the driver was being created _after_ the device was announced to userspace, causing a race with any tools looking for sysfs files. Fix the race by using the default attribute group for the class. Cc: Kees Cook Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/timed_output.c | 27 ++++++++++----------------- 1 file changed, 10 insertions(+), 17 deletions(-) diff --git a/drivers/staging/android/timed_output.c b/drivers/staging/android/timed_output.c index ee3a57f..2c61783 100644 --- a/drivers/staging/android/timed_output.c +++ b/drivers/staging/android/timed_output.c @@ -28,7 +28,7 @@ static struct class *timed_output_class; static atomic_t device_count; static ssize_t enable_show(struct device *dev, struct device_attribute *attr, - char *buf) + char *buf) { struct timed_output_dev *tdev = dev_get_drvdata(dev); int remaining = tdev->get_time(tdev); @@ -36,9 +36,8 @@ static ssize_t enable_show(struct device *dev, struct device_attribute *attr, return sprintf(buf, "%d\n", remaining); } -static ssize_t enable_store( - struct device *dev, struct device_attribute *attr, - const char *buf, size_t size) +static ssize_t enable_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t size) { struct timed_output_dev *tdev = dev_get_drvdata(dev); int value; @@ -50,8 +49,13 @@ static ssize_t enable_store( return size; } +static DEVICE_ATTR_RW(enable); -static DEVICE_ATTR(enable, S_IRUGO | S_IWUSR, enable_show, enable_store); +static struct attribute *timed_output_attrs[] = { + &dev_attr_enable.attr, + NULL, +}; +ATTRIBUTE_GROUPS(timed_output); static int create_timed_output_class(void) { @@ -60,6 +64,7 @@ static int create_timed_output_class(void) if (IS_ERR(timed_output_class)) return PTR_ERR(timed_output_class); atomic_set(&device_count, 0); + timed_output_class->dev_groups = timed_output_groups; } return 0; @@ -82,27 +87,15 @@ int timed_output_dev_register(struct timed_output_dev *tdev) if (IS_ERR(tdev->dev)) return PTR_ERR(tdev->dev); - ret = device_create_file(tdev->dev, &dev_attr_enable); - if (ret < 0) - goto err_create_file; - dev_set_drvdata(tdev->dev, tdev); tdev->state = 0; return 0; - -err_create_file: - device_destroy(timed_output_class, MKDEV(0, tdev->index)); - pr_err("failed to register driver %s\n", - tdev->name); - - return ret; } EXPORT_SYMBOL_GPL(timed_output_dev_register); void timed_output_dev_unregister(struct timed_output_dev *tdev) { tdev->enable(tdev, 0); - device_remove_file(tdev->dev, &dev_attr_enable); device_destroy(timed_output_class, MKDEV(0, tdev->index)); dev_set_drvdata(tdev->dev, NULL); } -- 2.7.4