Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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 <keescook@chromium.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

+10 -17
+10 -17
drivers/staging/android/timed_output.c
··· 28 28 static atomic_t device_count; 29 29 30 30 static ssize_t enable_show(struct device *dev, struct device_attribute *attr, 31 - char *buf) 31 + char *buf) 32 32 { 33 33 struct timed_output_dev *tdev = dev_get_drvdata(dev); 34 34 int remaining = tdev->get_time(tdev); ··· 36 36 return sprintf(buf, "%d\n", remaining); 37 37 } 38 38 39 - static ssize_t enable_store( 40 - struct device *dev, struct device_attribute *attr, 41 - const char *buf, size_t size) 39 + static ssize_t enable_store(struct device *dev, struct device_attribute *attr, 40 + const char *buf, size_t size) 42 41 { 43 42 struct timed_output_dev *tdev = dev_get_drvdata(dev); 44 43 int value; ··· 49 50 50 51 return size; 51 52 } 53 + static DEVICE_ATTR_RW(enable); 52 54 53 - static DEVICE_ATTR(enable, S_IRUGO | S_IWUSR, enable_show, enable_store); 55 + static struct attribute *timed_output_attrs[] = { 56 + &dev_attr_enable.attr, 57 + NULL, 58 + }; 59 + ATTRIBUTE_GROUPS(timed_output); 54 60 55 61 static int create_timed_output_class(void) 56 62 { ··· 64 60 if (IS_ERR(timed_output_class)) 65 61 return PTR_ERR(timed_output_class); 66 62 atomic_set(&device_count, 0); 63 + timed_output_class->dev_groups = timed_output_groups; 67 64 } 68 65 69 66 return 0; ··· 87 82 if (IS_ERR(tdev->dev)) 88 83 return PTR_ERR(tdev->dev); 89 84 90 - ret = device_create_file(tdev->dev, &dev_attr_enable); 91 - if (ret < 0) 92 - goto err_create_file; 93 - 94 85 dev_set_drvdata(tdev->dev, tdev); 95 86 tdev->state = 0; 96 87 return 0; 97 - 98 - err_create_file: 99 - device_destroy(timed_output_class, MKDEV(0, tdev->index)); 100 - pr_err("failed to register driver %s\n", 101 - tdev->name); 102 - 103 - return ret; 104 88 } 105 89 EXPORT_SYMBOL_GPL(timed_output_dev_register); 106 90 107 91 void timed_output_dev_unregister(struct timed_output_dev *tdev) 108 92 { 109 93 tdev->enable(tdev, 0); 110 - device_remove_file(tdev->dev, &dev_attr_enable); 111 94 device_destroy(timed_output_class, MKDEV(0, tdev->index)); 112 95 dev_set_drvdata(tdev->dev, NULL); 113 96 }