Skip to content

Commit

Permalink
gpio: sysfs: fix gpio device-attribute leak
Browse files Browse the repository at this point in the history
The gpio device attributes were never destroyed when the gpio was
unexported (or on export failures).

Use device_create_with_groups() to create the default device attributes
of the gpio class device. Note that this also fixes the
attribute-creation race with userspace for these attributes.

Remove contingent attributes in export error path and on unexport.

Fixes: d8f388d ("gpio: sysfs interface")
Cc: stable <stable@vger.kernel.org>	# v2.6.27+
Signed-off-by: Johan Hovold <johan@kernel.org>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
  • Loading branch information
Johan Hovold authored and Linus Walleij committed Jan 15, 2015
1 parent 121b6a7 commit 0915e6f
Showing 1 changed file with 13 additions and 15 deletions.
28 changes: 13 additions & 15 deletions drivers/gpio/gpiolib-sysfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ static ssize_t gpio_value_store(struct device *dev,
return status;
}

static const DEVICE_ATTR(value, 0644,
static DEVICE_ATTR(value, 0644,
gpio_value_show, gpio_value_store);

static irqreturn_t gpio_sysfs_irq(int irq, void *priv)
Expand Down Expand Up @@ -353,18 +353,15 @@ static ssize_t gpio_active_low_store(struct device *dev,
return status ? : size;
}

static const DEVICE_ATTR(active_low, 0644,
static DEVICE_ATTR(active_low, 0644,
gpio_active_low_show, gpio_active_low_store);

static const struct attribute *gpio_attrs[] = {
static struct attribute *gpio_attrs[] = {
&dev_attr_value.attr,
&dev_attr_active_low.attr,
NULL,
};

static const struct attribute_group gpio_attr_group = {
.attrs = (struct attribute **) gpio_attrs,
};
ATTRIBUTE_GROUPS(gpio);

/*
* /sys/class/gpio/gpiochipN/
Expand Down Expand Up @@ -561,18 +558,15 @@ int gpiod_export(struct gpio_desc *desc, bool direction_may_change)
if (desc->chip->names && desc->chip->names[offset])
ioname = desc->chip->names[offset];

dev = device_create(&gpio_class, desc->chip->dev, MKDEV(0, 0),
desc, ioname ? ioname : "gpio%u",
desc_to_gpio(desc));
dev = device_create_with_groups(&gpio_class, desc->chip->dev,
MKDEV(0, 0), desc, gpio_groups,
ioname ? ioname : "gpio%u",
desc_to_gpio(desc));
if (IS_ERR(dev)) {
status = PTR_ERR(dev);
goto fail_unlock;
}

status = sysfs_create_group(&dev->kobj, &gpio_attr_group);
if (status)
goto fail_unregister_device;

if (direction_may_change) {
status = device_create_file(dev, &dev_attr_direction);
if (status)
Expand All @@ -583,13 +577,15 @@ int gpiod_export(struct gpio_desc *desc, bool direction_may_change)
!test_bit(FLAG_IS_OUT, &desc->flags))) {
status = device_create_file(dev, &dev_attr_edge);
if (status)
goto fail_unregister_device;
goto fail_remove_attr_direction;
}

set_bit(FLAG_EXPORT, &desc->flags);
mutex_unlock(&sysfs_lock);
return 0;

fail_remove_attr_direction:
device_remove_file(dev, &dev_attr_direction);
fail_unregister_device:
device_unregister(dev);
fail_unlock:
Expand Down Expand Up @@ -723,6 +719,8 @@ void gpiod_unexport(struct gpio_desc *desc)
mutex_unlock(&sysfs_lock);

if (dev) {
device_remove_file(dev, &dev_attr_edge);
device_remove_file(dev, &dev_attr_direction);
device_unregister(dev);
put_device(dev);
}
Expand Down

0 comments on commit 0915e6f

Please sign in to comment.