diff options
Diffstat (limited to 'drivers/gpio/gpiolib.c')
-rw-r--r-- | drivers/gpio/gpiolib.c | 42 |
1 files changed, 41 insertions, 1 deletions
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]; |