aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohan Hovold <johan@kernel.org>2015-01-13 07:00:05 -0500
committerLinus Walleij <linus.walleij@linaro.org>2015-01-15 11:20:15 -0500
commit0915e6feb38de8d3601819992a5bd050201a56fa (patch)
tree246c1724e7a827583fa70147869b4bcbb15b883c
parent121b6a79955a3a3fd7bbb9b8cb88d5b9dad6283d (diff)
gpio: sysfs: fix gpio device-attribute leak
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: d8f388d8dc8d ("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>
-rw-r--r--drivers/gpio/gpiolib-sysfs.c28
1 files changed, 13 insertions, 15 deletions
diff --git a/drivers/gpio/gpiolib-sysfs.c b/drivers/gpio/gpiolib-sysfs.c
index 33cf4bd0ed2d..fd4d9423f6e6 100644
--- a/drivers/gpio/gpiolib-sysfs.c
+++ b/drivers/gpio/gpiolib-sysfs.c
@@ -128,7 +128,7 @@ static ssize_t gpio_value_store(struct device *dev,
128 return status; 128 return status;
129} 129}
130 130
131static const DEVICE_ATTR(value, 0644, 131static DEVICE_ATTR(value, 0644,
132 gpio_value_show, gpio_value_store); 132 gpio_value_show, gpio_value_store);
133 133
134static irqreturn_t gpio_sysfs_irq(int irq, void *priv) 134static irqreturn_t gpio_sysfs_irq(int irq, void *priv)
@@ -353,18 +353,15 @@ static ssize_t gpio_active_low_store(struct device *dev,
353 return status ? : size; 353 return status ? : size;
354} 354}
355 355
356static const DEVICE_ATTR(active_low, 0644, 356static DEVICE_ATTR(active_low, 0644,
357 gpio_active_low_show, gpio_active_low_store); 357 gpio_active_low_show, gpio_active_low_store);
358 358
359static const struct attribute *gpio_attrs[] = { 359static struct attribute *gpio_attrs[] = {
360 &dev_attr_value.attr, 360 &dev_attr_value.attr,
361 &dev_attr_active_low.attr, 361 &dev_attr_active_low.attr,
362 NULL, 362 NULL,
363}; 363};
364 364ATTRIBUTE_GROUPS(gpio);
365static const struct attribute_group gpio_attr_group = {
366 .attrs = (struct attribute **) gpio_attrs,
367};
368 365
369/* 366/*
370 * /sys/class/gpio/gpiochipN/ 367 * /sys/class/gpio/gpiochipN/
@@ -561,18 +558,15 @@ int gpiod_export(struct gpio_desc *desc, bool direction_may_change)
561 if (desc->chip->names && desc->chip->names[offset]) 558 if (desc->chip->names && desc->chip->names[offset])
562 ioname = desc->chip->names[offset]; 559 ioname = desc->chip->names[offset];
563 560
564 dev = device_create(&gpio_class, desc->chip->dev, MKDEV(0, 0), 561 dev = device_create_with_groups(&gpio_class, desc->chip->dev,
565 desc, ioname ? ioname : "gpio%u", 562 MKDEV(0, 0), desc, gpio_groups,
566 desc_to_gpio(desc)); 563 ioname ? ioname : "gpio%u",
564 desc_to_gpio(desc));
567 if (IS_ERR(dev)) { 565 if (IS_ERR(dev)) {
568 status = PTR_ERR(dev); 566 status = PTR_ERR(dev);
569 goto fail_unlock; 567 goto fail_unlock;
570 } 568 }
571 569
572 status = sysfs_create_group(&dev->kobj, &gpio_attr_group);
573 if (status)
574 goto fail_unregister_device;
575
576 if (direction_may_change) { 570 if (direction_may_change) {
577 status = device_create_file(dev, &dev_attr_direction); 571 status = device_create_file(dev, &dev_attr_direction);
578 if (status) 572 if (status)
@@ -583,13 +577,15 @@ int gpiod_export(struct gpio_desc *desc, bool direction_may_change)
583 !test_bit(FLAG_IS_OUT, &desc->flags))) { 577 !test_bit(FLAG_IS_OUT, &desc->flags))) {
584 status = device_create_file(dev, &dev_attr_edge); 578 status = device_create_file(dev, &dev_attr_edge);
585 if (status) 579 if (status)
586 goto fail_unregister_device; 580 goto fail_remove_attr_direction;
587 } 581 }
588 582
589 set_bit(FLAG_EXPORT, &desc->flags); 583 set_bit(FLAG_EXPORT, &desc->flags);
590 mutex_unlock(&sysfs_lock); 584 mutex_unlock(&sysfs_lock);
591 return 0; 585 return 0;
592 586
587fail_remove_attr_direction:
588 device_remove_file(dev, &dev_attr_direction);
593fail_unregister_device: 589fail_unregister_device:
594 device_unregister(dev); 590 device_unregister(dev);
595fail_unlock: 591fail_unlock:
@@ -723,6 +719,8 @@ void gpiod_unexport(struct gpio_desc *desc)
723 mutex_unlock(&sysfs_lock); 719 mutex_unlock(&sysfs_lock);
724 720
725 if (dev) { 721 if (dev) {
722 device_remove_file(dev, &dev_attr_edge);
723 device_remove_file(dev, &dev_attr_direction);
726 device_unregister(dev); 724 device_unregister(dev);
727 put_device(dev); 725 put_device(dev);
728 } 726 }