Commit 9d3ab801 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman
Browse files

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: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 76e1f486
Loading
Loading
Loading
Loading
+10 −17
Original line number Diff line number Diff line
@@ -36,8 +36,7 @@ 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,
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);
@@ -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);
}