]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - releases/3.10.67/gpio-sysfs-fix-gpio-device-attribute-leak.patch
4.14-stable patches
[thirdparty/kernel/stable-queue.git] / releases / 3.10.67 / gpio-sysfs-fix-gpio-device-attribute-leak.patch
1 From 0915e6feb38de8d3601819992a5bd050201a56fa Mon Sep 17 00:00:00 2001
2 From: Johan Hovold <johan@kernel.org>
3 Date: Tue, 13 Jan 2015 13:00:05 +0100
4 Subject: gpio: sysfs: fix gpio device-attribute leak
5
6 From: Johan Hovold <johan@kernel.org>
7
8 commit 0915e6feb38de8d3601819992a5bd050201a56fa upstream.
9
10 The gpio device attributes were never destroyed when the gpio was
11 unexported (or on export failures).
12
13 Use device_create_with_groups() to create the default device attributes
14 of the gpio class device. Note that this also fixes the
15 attribute-creation race with userspace for these attributes.
16
17 Remove contingent attributes in export error path and on unexport.
18
19 Fixes: d8f388d8dc8d ("gpio: sysfs interface")
20 Cc: stable <stable@vger.kernel.org> # v2.6.27+
21 Signed-off-by: Johan Hovold <johan@kernel.org>
22 Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
23 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
24
25 ---
26 drivers/gpio/gpiolib.c | 19 +++++++++++++------
27 1 file changed, 13 insertions(+), 6 deletions(-)
28
29 --- a/drivers/gpio/gpiolib.c
30 +++ b/drivers/gpio/gpiolib.c
31 @@ -362,7 +362,7 @@ static ssize_t gpio_value_store(struct d
32 return status;
33 }
34
35 -static const DEVICE_ATTR(value, 0644,
36 +static DEVICE_ATTR(value, 0644,
37 gpio_value_show, gpio_value_store);
38
39 static irqreturn_t gpio_sysfs_irq(int irq, void *priv)
40 @@ -580,17 +580,17 @@ static ssize_t gpio_active_low_store(str
41 return status ? : size;
42 }
43
44 -static const DEVICE_ATTR(active_low, 0644,
45 +static DEVICE_ATTR(active_low, 0644,
46 gpio_active_low_show, gpio_active_low_store);
47
48 -static const struct attribute *gpio_attrs[] = {
49 +static struct attribute *gpio_attrs[] = {
50 &dev_attr_value.attr,
51 &dev_attr_active_low.attr,
52 NULL,
53 };
54
55 static const struct attribute_group gpio_attr_group = {
56 - .attrs = (struct attribute **) gpio_attrs,
57 + .attrs = gpio_attrs,
58 };
59
60 /*
61 @@ -806,20 +806,24 @@ static int gpiod_export(struct gpio_desc
62 if (direction_may_change) {
63 status = device_create_file(dev, &dev_attr_direction);
64 if (status)
65 - goto fail_unregister_device;
66 + goto fail_remove_attr_group;
67 }
68
69 if (gpiod_to_irq(desc) >= 0 && (direction_may_change ||
70 !test_bit(FLAG_IS_OUT, &desc->flags))) {
71 status = device_create_file(dev, &dev_attr_edge);
72 if (status)
73 - goto fail_unregister_device;
74 + goto fail_remove_attr_direction;
75 }
76
77 set_bit(FLAG_EXPORT, &desc->flags);
78 mutex_unlock(&sysfs_lock);
79 return 0;
80
81 +fail_remove_attr_direction:
82 + device_remove_file(dev, &dev_attr_direction);
83 +fail_remove_attr_group:
84 + sysfs_remove_group(&dev->kobj, &gpio_attr_group);
85 fail_unregister_device:
86 device_unregister(dev);
87 fail_unlock:
88 @@ -971,6 +975,9 @@ static void gpiod_unexport(struct gpio_d
89 mutex_unlock(&sysfs_lock);
90
91 if (dev) {
92 + device_remove_file(dev, &dev_attr_edge);
93 + device_remove_file(dev, &dev_attr_direction);
94 + sysfs_remove_group(&dev->kobj, &gpio_attr_group);
95 device_unregister(dev);
96 put_device(dev);
97 }