Skip to content

Commit 1ce5bdb

Browse files
committed
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
2 parents aa34e07 + d71cf15 commit 1ce5bdb

File tree

9 files changed

+64
-12
lines changed

9 files changed

+64
-12
lines changed

Documentation/gpio/board.txt

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ Note that it only applies to the new descriptor-based interface. For a
66
description of the deprecated integer-based GPIO interface please refer to
77
gpio-legacy.txt (actually, there is no real mapping possible with the old
88
interface; you just fetch an integer from somewhere and request the
9-
corresponding GPIO.
9+
corresponding GPIO).
1010

1111
All platforms can enable the GPIO library, but if the platform strictly
1212
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:
162162

163163
Since the "led" GPIOs are mapped as active-high, this example will switch their
164164
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
166-
integer GPIO interface, the active-low property is handled during mapping and is
167-
thus transparent to GPIO consumers.
165+
as active-low, its actual signal will be 0 after this code. Contrary to the
166+
legacy integer GPIO interface, the active-low property is handled during
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.

drivers/gpio/Kconfig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -284,7 +284,7 @@ config GPIO_MM_LANTIQ
284284

285285
config GPIO_MOCKUP
286286
tristate "GPIO Testing Driver"
287-
depends on GPIOLIB
287+
depends on GPIOLIB && SYSFS
288288
select GPIO_SYSFS
289289
help
290290
This enables GPIO Testing driver, which provides a way to test GPIO

drivers/gpio/gpio-ath79.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,7 @@ static const struct of_device_id ath79_gpio_of_match[] = {
219219
{ .compatible = "qca,ar9340-gpio" },
220220
{},
221221
};
222+
MODULE_DEVICE_TABLE(of, ath79_gpio_of_match);
222223

223224
static int ath79_gpio_probe(struct platform_device *pdev)
224225
{

drivers/gpio/gpio-mpc8xxx.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,7 @@ static int mpc8xxx_gpio_irq_map(struct irq_domain *h, unsigned int irq,
239239
irq_hw_number_t hwirq)
240240
{
241241
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);
243243

244244
return 0;
245245
}

drivers/gpio/gpio-mxs.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -308,8 +308,10 @@ static int mxs_gpio_probe(struct platform_device *pdev)
308308
writel(~0U, port->base + PINCTRL_IRQSTAT(port) + MXS_CLR);
309309

310310
irq_base = irq_alloc_descs(-1, 0, 32, numa_node_id());
311-
if (irq_base < 0)
312-
return irq_base;
311+
if (irq_base < 0) {
312+
err = irq_base;
313+
goto out_iounmap;
314+
}
313315

314316
port->domain = irq_domain_add_legacy(np, 32, irq_base, 0,
315317
&irq_domain_simple_ops, NULL);
@@ -349,6 +351,8 @@ static int mxs_gpio_probe(struct platform_device *pdev)
349351
irq_domain_remove(port->domain);
350352
out_irqdesc_free:
351353
irq_free_descs(irq_base, 32);
354+
out_iounmap:
355+
iounmap(port->base);
352356
return err;
353357
}
354358

drivers/gpio/gpio-stmpe.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -409,7 +409,7 @@ static irqreturn_t stmpe_gpio_irq(int irq, void *dev)
409409
* 801/1801/1600, bits are cleared when read.
410410
* Edge detect register is not present on 801/1600/1801
411411
*/
412-
if (stmpe->partnum != STMPE801 || stmpe->partnum != STMPE1600 ||
412+
if (stmpe->partnum != STMPE801 && stmpe->partnum != STMPE1600 &&
413413
stmpe->partnum != STMPE1801) {
414414
stmpe_reg_write(stmpe, statmsbreg + i, status[i]);
415415
stmpe_reg_write(stmpe,

drivers/gpio/gpio-ts4800.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ static const struct of_device_id ts4800_gpio_of_match[] = {
6666
{ .compatible = "technologic,ts4800-gpio", },
6767
{},
6868
};
69+
MODULE_DEVICE_TABLE(of, ts4800_gpio_of_match);
6970

7071
static struct platform_driver ts4800_gpio_driver = {
7172
.driver = {

drivers/gpio/gpiolib-acpi.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -653,14 +653,17 @@ int acpi_dev_gpio_irq_get(struct acpi_device *adev, int index)
653653
{
654654
int idx, i;
655655
unsigned int irq_flags;
656+
int ret = -ENOENT;
656657

657658
for (i = 0, idx = 0; idx <= index; i++) {
658659
struct acpi_gpio_info info;
659660
struct gpio_desc *desc;
660661

661662
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);
663665
break;
666+
}
664667
if (info.gpioint && idx++ == index) {
665668
int irq = gpiod_to_irq(desc);
666669

@@ -679,7 +682,7 @@ int acpi_dev_gpio_irq_get(struct acpi_device *adev, int index)
679682
}
680683

681684
}
682-
return -ENOENT;
685+
return ret;
683686
}
684687
EXPORT_SYMBOL_GPL(acpi_dev_gpio_irq_get);
685688

drivers/gpio/gpiolib.c

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,13 @@ struct linehandle_state {
333333
u32 numdescs;
334334
};
335335

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+
336343
static long linehandle_ioctl(struct file *filep, unsigned int cmd,
337344
unsigned long arg)
338345
{
@@ -344,6 +351,8 @@ static long linehandle_ioctl(struct file *filep, unsigned int cmd,
344351
if (cmd == GPIOHANDLE_GET_LINE_VALUES_IOCTL) {
345352
int val;
346353

354+
memset(&ghd, 0, sizeof(ghd));
355+
347356
/* TODO: check if descriptors are really input */
348357
for (i = 0; i < lh->numdescs; i++) {
349358
val = gpiod_get_value_cansleep(lh->descs[i]);
@@ -444,6 +453,17 @@ static int linehandle_create(struct gpio_device *gdev, void __user *ip)
444453
u32 lflags = handlereq.flags;
445454
struct gpio_desc *desc;
446455

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+
447467
desc = &gdev->descs[offset];
448468
ret = gpiod_request(desc, lh->label);
449469
if (ret)
@@ -536,6 +556,10 @@ struct lineevent_state {
536556
struct mutex read_lock;
537557
};
538558

559+
#define GPIOEVENT_REQUEST_VALID_FLAGS \
560+
(GPIOEVENT_REQUEST_RISING_EDGE | \
561+
GPIOEVENT_REQUEST_FALLING_EDGE)
562+
539563
static unsigned int lineevent_poll(struct file *filep,
540564
struct poll_table_struct *wait)
541565
{
@@ -623,6 +647,8 @@ static long lineevent_ioctl(struct file *filep, unsigned int cmd,
623647
if (cmd == GPIOHANDLE_GET_LINE_VALUES_IOCTL) {
624648
int val;
625649

650+
memset(&ghd, 0, sizeof(ghd));
651+
626652
val = gpiod_get_value_cansleep(le->desc);
627653
if (val < 0)
628654
return val;
@@ -726,6 +752,18 @@ static int lineevent_create(struct gpio_device *gdev, void __user *ip)
726752
lflags = eventreq.handleflags;
727753
eflags = eventreq.eventflags;
728754

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+
729767
/* This is just wrong: we don't look for events on output lines */
730768
if (lflags & GPIOHANDLE_REQUEST_OUTPUT) {
731769
ret = -EINVAL;
@@ -823,6 +861,8 @@ static long gpio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
823861
if (cmd == GPIO_GET_CHIPINFO_IOCTL) {
824862
struct gpiochip_info chipinfo;
825863

864+
memset(&chipinfo, 0, sizeof(chipinfo));
865+
826866
strncpy(chipinfo.name, dev_name(&gdev->dev),
827867
sizeof(chipinfo.name));
828868
chipinfo.name[sizeof(chipinfo.name)-1] = '\0';
@@ -839,7 +879,7 @@ static long gpio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
839879

840880
if (copy_from_user(&lineinfo, ip, sizeof(lineinfo)))
841881
return -EFAULT;
842-
if (lineinfo.line_offset > gdev->ngpio)
882+
if (lineinfo.line_offset >= gdev->ngpio)
843883
return -EINVAL;
844884

845885
desc = &gdev->descs[lineinfo.line_offset];

0 commit comments

Comments
 (0)