diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-10-25 00:19:07 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-10-25 00:19:07 -0400 |
commit | 1ce5bdb8312b6e9629029340063ea1e5cfac435d (patch) | |
tree | c47706ca6b30ff50ec204e5abfb5ee22dc841e48 | |
parent | aa34e07e457ed13b44d680b5b605e3e5a585f611 (diff) | |
parent | d71cf15b865bdd45925f7b094d169aaabd705145 (diff) |
Merge tag 'gpio-v4.9-2' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio
Pull GPIO fixes from Linus Walleij:
"Here is a set of GPIO fixes for the v4.9 kernel series:
- Fix up off-by one and line offset validation, info leak to
userspace, and reject invalid flags. Those are especially valuable
hardening patches from Lars-Peter Clausen, all tagged for stable.
- Fix module autoload for TS4800 and ATH79.
- Correct the IRQ handler for MPC8xxx to use handle_level_irq() as it
(a) reacts to edges not levels and (b) even implements .irq_ack().
We were missing IRQs here.
- Fix the error path for acpi_dev_gpio_irq_get()
- Fix a memory leak in the MXS driver.
- Fix an annoying typo in the STMPE driver.
- Put a dependency on sysfs to the mockup driver"
* tag 'gpio-v4.9-2' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio:
gpio: mpc8xxx: Correct irq handler function
gpio: ath79: Fix module autoload
gpio: ts4800: Fix module autoload
gpio: GPIO_GET_LINEEVENT_IOCTL: Reject invalid line and event flags
gpio: GPIO_GET_LINEHANDLE_IOCTL: Reject invalid line flags
gpio: GPIOHANDLE_GET_LINE_VALUES_IOCTL: Fix information leak
gpio: GPIO_GET_LINEEVENT_IOCTL: Validate line offset
gpio: GPIOHANDLE_GET_LINE_VALUES_IOCTL: Fix information leak
gpio: GPIO_GET_LINEHANDLE_IOCTL: Validate line offset
gpio: GPIO_GET_CHIPINFO_IOCTL: Fix information leak
gpio: GPIO_GET_CHIPINFO_IOCTL: Fix line offset validation
gpio / ACPI: fix returned error from acpi_dev_gpio_irq_get()
gpio: mockup: add sysfs dependency
gpio: stmpe: || vs && typo
gpio: mxs: Unmap region obtained by of_iomap
gpio/board.txt: point to gpiod_set_value
-rw-r--r-- | Documentation/gpio/board.txt | 11 | ||||
-rw-r--r-- | drivers/gpio/Kconfig | 2 | ||||
-rw-r--r-- | drivers/gpio/gpio-ath79.c | 1 | ||||
-rw-r--r-- | drivers/gpio/gpio-mpc8xxx.c | 2 | ||||
-rw-r--r-- | drivers/gpio/gpio-mxs.c | 8 | ||||
-rw-r--r-- | drivers/gpio/gpio-stmpe.c | 2 | ||||
-rw-r--r-- | drivers/gpio/gpio-ts4800.c | 1 | ||||
-rw-r--r-- | drivers/gpio/gpiolib-acpi.c | 7 | ||||
-rw-r--r-- | drivers/gpio/gpiolib.c | 42 |
9 files changed, 64 insertions, 12 deletions
diff --git a/Documentation/gpio/board.txt b/Documentation/gpio/board.txt index 40884c4fe40c..a0f61898d493 100644 --- a/Documentation/gpio/board.txt +++ b/Documentation/gpio/board.txt | |||
@@ -6,7 +6,7 @@ Note that it only applies to the new descriptor-based interface. For a | |||
6 | description of the deprecated integer-based GPIO interface please refer to | 6 | description of the deprecated integer-based GPIO interface please refer to |
7 | gpio-legacy.txt (actually, there is no real mapping possible with the old | 7 | gpio-legacy.txt (actually, there is no real mapping possible with the old |
8 | interface; you just fetch an integer from somewhere and request the | 8 | interface; you just fetch an integer from somewhere and request the |
9 | corresponding GPIO. | 9 | corresponding GPIO). |
10 | 10 | ||
11 | All platforms can enable the GPIO library, but if the platform strictly | 11 | All platforms can enable the GPIO library, but if the platform strictly |
12 | requires GPIO functionality to be present, it needs to select GPIOLIB from its | 12 | requires GPIO functionality to be present, it needs to select GPIOLIB from its |
@@ -162,6 +162,9 @@ The driver controlling "foo.0" will then be able to obtain its GPIOs as follows: | |||
162 | 162 | ||
163 | Since the "led" GPIOs are mapped as active-high, this example will switch their | 163 | Since the "led" GPIOs are mapped as active-high, this example will switch their |
164 | signals to 1, i.e. enabling the LEDs. And for the "power" GPIO, which is mapped | 164 | signals to 1, i.e. enabling the LEDs. And for the "power" GPIO, which is mapped |
165 | as active-low, its actual signal will be 0 after this code. Contrary to the legacy | 165 | as active-low, its actual signal will be 0 after this code. Contrary to the |
166 | integer GPIO interface, the active-low property is handled during mapping and is | 166 | legacy integer GPIO interface, the active-low property is handled during |
167 | thus transparent to GPIO consumers. | 167 | mapping and is thus transparent to GPIO consumers. |
168 | |||
169 | A set of functions such as gpiod_set_value() is available to work with | ||
170 | the new descriptor-oriented interface. | ||
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 26ee00f6bd58..d011cb89d25e 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig | |||
@@ -284,7 +284,7 @@ config GPIO_MM_LANTIQ | |||
284 | 284 | ||
285 | config GPIO_MOCKUP | 285 | config GPIO_MOCKUP |
286 | tristate "GPIO Testing Driver" | 286 | tristate "GPIO Testing Driver" |
287 | depends on GPIOLIB | 287 | depends on GPIOLIB && SYSFS |
288 | select GPIO_SYSFS | 288 | select GPIO_SYSFS |
289 | help | 289 | help |
290 | This enables GPIO Testing driver, which provides a way to test GPIO | 290 | This enables GPIO Testing driver, which provides a way to test GPIO |
diff --git a/drivers/gpio/gpio-ath79.c b/drivers/gpio/gpio-ath79.c index 9457e2022bf6..dc37dbe4b46d 100644 --- a/drivers/gpio/gpio-ath79.c +++ b/drivers/gpio/gpio-ath79.c | |||
@@ -219,6 +219,7 @@ static const struct of_device_id ath79_gpio_of_match[] = { | |||
219 | { .compatible = "qca,ar9340-gpio" }, | 219 | { .compatible = "qca,ar9340-gpio" }, |
220 | {}, | 220 | {}, |
221 | }; | 221 | }; |
222 | MODULE_DEVICE_TABLE(of, ath79_gpio_of_match); | ||
222 | 223 | ||
223 | static int ath79_gpio_probe(struct platform_device *pdev) | 224 | static int ath79_gpio_probe(struct platform_device *pdev) |
224 | { | 225 | { |
diff --git a/drivers/gpio/gpio-mpc8xxx.c b/drivers/gpio/gpio-mpc8xxx.c index 425501c39527..793518a30afe 100644 --- a/drivers/gpio/gpio-mpc8xxx.c +++ b/drivers/gpio/gpio-mpc8xxx.c | |||
@@ -239,7 +239,7 @@ static int mpc8xxx_gpio_irq_map(struct irq_domain *h, unsigned int irq, | |||
239 | irq_hw_number_t hwirq) | 239 | irq_hw_number_t hwirq) |
240 | { | 240 | { |
241 | irq_set_chip_data(irq, h->host_data); | 241 | irq_set_chip_data(irq, h->host_data); |
242 | irq_set_chip_and_handler(irq, &mpc8xxx_irq_chip, handle_level_irq); | 242 | irq_set_chip_and_handler(irq, &mpc8xxx_irq_chip, handle_edge_irq); |
243 | 243 | ||
244 | return 0; | 244 | return 0; |
245 | } | 245 | } |
diff --git a/drivers/gpio/gpio-mxs.c b/drivers/gpio/gpio-mxs.c index b9daa0bf32a4..ee1724806f46 100644 --- a/drivers/gpio/gpio-mxs.c +++ b/drivers/gpio/gpio-mxs.c | |||
@@ -308,8 +308,10 @@ static int mxs_gpio_probe(struct platform_device *pdev) | |||
308 | writel(~0U, port->base + PINCTRL_IRQSTAT(port) + MXS_CLR); | 308 | writel(~0U, port->base + PINCTRL_IRQSTAT(port) + MXS_CLR); |
309 | 309 | ||
310 | irq_base = irq_alloc_descs(-1, 0, 32, numa_node_id()); | 310 | irq_base = irq_alloc_descs(-1, 0, 32, numa_node_id()); |
311 | if (irq_base < 0) | 311 | if (irq_base < 0) { |
312 | return irq_base; | 312 | err = irq_base; |
313 | goto out_iounmap; | ||
314 | } | ||
313 | 315 | ||
314 | port->domain = irq_domain_add_legacy(np, 32, irq_base, 0, | 316 | port->domain = irq_domain_add_legacy(np, 32, irq_base, 0, |
315 | &irq_domain_simple_ops, NULL); | 317 | &irq_domain_simple_ops, NULL); |
@@ -349,6 +351,8 @@ out_irqdomain_remove: | |||
349 | irq_domain_remove(port->domain); | 351 | irq_domain_remove(port->domain); |
350 | out_irqdesc_free: | 352 | out_irqdesc_free: |
351 | irq_free_descs(irq_base, 32); | 353 | irq_free_descs(irq_base, 32); |
354 | out_iounmap: | ||
355 | iounmap(port->base); | ||
352 | return err; | 356 | return err; |
353 | } | 357 | } |
354 | 358 | ||
diff --git a/drivers/gpio/gpio-stmpe.c b/drivers/gpio/gpio-stmpe.c index e7d422a6b90b..5b0042776ec7 100644 --- a/drivers/gpio/gpio-stmpe.c +++ b/drivers/gpio/gpio-stmpe.c | |||
@@ -409,7 +409,7 @@ static irqreturn_t stmpe_gpio_irq(int irq, void *dev) | |||
409 | * 801/1801/1600, bits are cleared when read. | 409 | * 801/1801/1600, bits are cleared when read. |
410 | * Edge detect register is not present on 801/1600/1801 | 410 | * Edge detect register is not present on 801/1600/1801 |
411 | */ | 411 | */ |
412 | if (stmpe->partnum != STMPE801 || stmpe->partnum != STMPE1600 || | 412 | if (stmpe->partnum != STMPE801 && stmpe->partnum != STMPE1600 && |
413 | stmpe->partnum != STMPE1801) { | 413 | stmpe->partnum != STMPE1801) { |
414 | stmpe_reg_write(stmpe, statmsbreg + i, status[i]); | 414 | stmpe_reg_write(stmpe, statmsbreg + i, status[i]); |
415 | stmpe_reg_write(stmpe, | 415 | stmpe_reg_write(stmpe, |
diff --git a/drivers/gpio/gpio-ts4800.c b/drivers/gpio/gpio-ts4800.c index 99256115bea5..c2a80b4cbf32 100644 --- a/drivers/gpio/gpio-ts4800.c +++ b/drivers/gpio/gpio-ts4800.c | |||
@@ -66,6 +66,7 @@ static const struct of_device_id ts4800_gpio_of_match[] = { | |||
66 | { .compatible = "technologic,ts4800-gpio", }, | 66 | { .compatible = "technologic,ts4800-gpio", }, |
67 | {}, | 67 | {}, |
68 | }; | 68 | }; |
69 | MODULE_DEVICE_TABLE(of, ts4800_gpio_of_match); | ||
69 | 70 | ||
70 | static struct platform_driver ts4800_gpio_driver = { | 71 | static struct platform_driver ts4800_gpio_driver = { |
71 | .driver = { | 72 | .driver = { |
diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c index 58ece201b8e6..72a4b326fd0d 100644 --- a/drivers/gpio/gpiolib-acpi.c +++ b/drivers/gpio/gpiolib-acpi.c | |||
@@ -653,14 +653,17 @@ int acpi_dev_gpio_irq_get(struct acpi_device *adev, int index) | |||
653 | { | 653 | { |
654 | int idx, i; | 654 | int idx, i; |
655 | unsigned int irq_flags; | 655 | unsigned int irq_flags; |
656 | int ret = -ENOENT; | ||
656 | 657 | ||
657 | for (i = 0, idx = 0; idx <= index; i++) { | 658 | for (i = 0, idx = 0; idx <= index; i++) { |
658 | struct acpi_gpio_info info; | 659 | struct acpi_gpio_info info; |
659 | struct gpio_desc *desc; | 660 | struct gpio_desc *desc; |
660 | 661 | ||
661 | desc = acpi_get_gpiod_by_index(adev, NULL, i, &info); | 662 | desc = acpi_get_gpiod_by_index(adev, NULL, i, &info); |
662 | if (IS_ERR(desc)) | 663 | if (IS_ERR(desc)) { |
664 | ret = PTR_ERR(desc); | ||
663 | break; | 665 | break; |
666 | } | ||
664 | if (info.gpioint && idx++ == index) { | 667 | if (info.gpioint && idx++ == index) { |
665 | int irq = gpiod_to_irq(desc); | 668 | int irq = gpiod_to_irq(desc); |
666 | 669 | ||
@@ -679,7 +682,7 @@ int acpi_dev_gpio_irq_get(struct acpi_device *adev, int index) | |||
679 | } | 682 | } |
680 | 683 | ||
681 | } | 684 | } |
682 | return -ENOENT; | 685 | return ret; |
683 | } | 686 | } |
684 | EXPORT_SYMBOL_GPL(acpi_dev_gpio_irq_get); | 687 | EXPORT_SYMBOL_GPL(acpi_dev_gpio_irq_get); |
685 | 688 | ||
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index f0fc3a0d37c8..20e09b7c2de3 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c | |||
@@ -333,6 +333,13 @@ struct linehandle_state { | |||
333 | u32 numdescs; | 333 | u32 numdescs; |
334 | }; | 334 | }; |
335 | 335 | ||
336 | #define GPIOHANDLE_REQUEST_VALID_FLAGS \ | ||
337 | (GPIOHANDLE_REQUEST_INPUT | \ | ||
338 | GPIOHANDLE_REQUEST_OUTPUT | \ | ||
339 | GPIOHANDLE_REQUEST_ACTIVE_LOW | \ | ||
340 | GPIOHANDLE_REQUEST_OPEN_DRAIN | \ | ||
341 | GPIOHANDLE_REQUEST_OPEN_SOURCE) | ||
342 | |||
336 | static long linehandle_ioctl(struct file *filep, unsigned int cmd, | 343 | static long linehandle_ioctl(struct file *filep, unsigned int cmd, |
337 | unsigned long arg) | 344 | unsigned long arg) |
338 | { | 345 | { |
@@ -344,6 +351,8 @@ static long linehandle_ioctl(struct file *filep, unsigned int cmd, | |||
344 | if (cmd == GPIOHANDLE_GET_LINE_VALUES_IOCTL) { | 351 | if (cmd == GPIOHANDLE_GET_LINE_VALUES_IOCTL) { |
345 | int val; | 352 | int val; |
346 | 353 | ||
354 | memset(&ghd, 0, sizeof(ghd)); | ||
355 | |||
347 | /* TODO: check if descriptors are really input */ | 356 | /* TODO: check if descriptors are really input */ |
348 | for (i = 0; i < lh->numdescs; i++) { | 357 | for (i = 0; i < lh->numdescs; i++) { |
349 | val = gpiod_get_value_cansleep(lh->descs[i]); | 358 | val = gpiod_get_value_cansleep(lh->descs[i]); |
@@ -444,6 +453,17 @@ static int linehandle_create(struct gpio_device *gdev, void __user *ip) | |||
444 | u32 lflags = handlereq.flags; | 453 | u32 lflags = handlereq.flags; |
445 | struct gpio_desc *desc; | 454 | struct gpio_desc *desc; |
446 | 455 | ||
456 | if (offset >= gdev->ngpio) { | ||
457 | ret = -EINVAL; | ||
458 | goto out_free_descs; | ||
459 | } | ||
460 | |||
461 | /* Return an error if a unknown flag is set */ | ||
462 | if (lflags & ~GPIOHANDLE_REQUEST_VALID_FLAGS) { | ||
463 | ret = -EINVAL; | ||
464 | goto out_free_descs; | ||
465 | } | ||
466 | |||
447 | desc = &gdev->descs[offset]; | 467 | desc = &gdev->descs[offset]; |
448 | ret = gpiod_request(desc, lh->label); | 468 | ret = gpiod_request(desc, lh->label); |
449 | if (ret) | 469 | if (ret) |
@@ -536,6 +556,10 @@ struct lineevent_state { | |||
536 | struct mutex read_lock; | 556 | struct mutex read_lock; |
537 | }; | 557 | }; |
538 | 558 | ||
559 | #define GPIOEVENT_REQUEST_VALID_FLAGS \ | ||
560 | (GPIOEVENT_REQUEST_RISING_EDGE | \ | ||
561 | GPIOEVENT_REQUEST_FALLING_EDGE) | ||
562 | |||
539 | static unsigned int lineevent_poll(struct file *filep, | 563 | static unsigned int lineevent_poll(struct file *filep, |
540 | struct poll_table_struct *wait) | 564 | struct poll_table_struct *wait) |
541 | { | 565 | { |
@@ -623,6 +647,8 @@ static long lineevent_ioctl(struct file *filep, unsigned int cmd, | |||
623 | if (cmd == GPIOHANDLE_GET_LINE_VALUES_IOCTL) { | 647 | if (cmd == GPIOHANDLE_GET_LINE_VALUES_IOCTL) { |
624 | int val; | 648 | int val; |
625 | 649 | ||
650 | memset(&ghd, 0, sizeof(ghd)); | ||
651 | |||
626 | val = gpiod_get_value_cansleep(le->desc); | 652 | val = gpiod_get_value_cansleep(le->desc); |
627 | if (val < 0) | 653 | if (val < 0) |
628 | return val; | 654 | return val; |
@@ -726,6 +752,18 @@ static int lineevent_create(struct gpio_device *gdev, void __user *ip) | |||
726 | lflags = eventreq.handleflags; | 752 | lflags = eventreq.handleflags; |
727 | eflags = eventreq.eventflags; | 753 | eflags = eventreq.eventflags; |
728 | 754 | ||
755 | if (offset >= gdev->ngpio) { | ||
756 | ret = -EINVAL; | ||
757 | goto out_free_label; | ||
758 | } | ||
759 | |||
760 | /* Return an error if a unknown flag is set */ | ||
761 | if ((lflags & ~GPIOHANDLE_REQUEST_VALID_FLAGS) || | ||
762 | (eflags & ~GPIOEVENT_REQUEST_VALID_FLAGS)) { | ||
763 | ret = -EINVAL; | ||
764 | goto out_free_label; | ||
765 | } | ||
766 | |||
729 | /* This is just wrong: we don't look for events on output lines */ | 767 | /* This is just wrong: we don't look for events on output lines */ |
730 | if (lflags & GPIOHANDLE_REQUEST_OUTPUT) { | 768 | if (lflags & GPIOHANDLE_REQUEST_OUTPUT) { |
731 | ret = -EINVAL; | 769 | ret = -EINVAL; |
@@ -823,6 +861,8 @@ static long gpio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) | |||
823 | if (cmd == GPIO_GET_CHIPINFO_IOCTL) { | 861 | if (cmd == GPIO_GET_CHIPINFO_IOCTL) { |
824 | struct gpiochip_info chipinfo; | 862 | struct gpiochip_info chipinfo; |
825 | 863 | ||
864 | memset(&chipinfo, 0, sizeof(chipinfo)); | ||
865 | |||
826 | strncpy(chipinfo.name, dev_name(&gdev->dev), | 866 | strncpy(chipinfo.name, dev_name(&gdev->dev), |
827 | sizeof(chipinfo.name)); | 867 | sizeof(chipinfo.name)); |
828 | chipinfo.name[sizeof(chipinfo.name)-1] = '\0'; | 868 | chipinfo.name[sizeof(chipinfo.name)-1] = '\0'; |
@@ -839,7 +879,7 @@ static long gpio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) | |||
839 | 879 | ||
840 | if (copy_from_user(&lineinfo, ip, sizeof(lineinfo))) | 880 | if (copy_from_user(&lineinfo, ip, sizeof(lineinfo))) |
841 | return -EFAULT; | 881 | return -EFAULT; |
842 | if (lineinfo.line_offset > gdev->ngpio) | 882 | if (lineinfo.line_offset >= gdev->ngpio) |
843 | return -EINVAL; | 883 | return -EINVAL; |
844 | 884 | ||
845 | desc = &gdev->descs[lineinfo.line_offset]; | 885 | desc = &gdev->descs[lineinfo.line_offset]; |