aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpio/gpiolib.c57
1 files changed, 45 insertions, 12 deletions
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 20e09b7c2de3..93ed0e00c578 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -21,6 +21,7 @@
21#include <linux/uaccess.h> 21#include <linux/uaccess.h>
22#include <linux/compat.h> 22#include <linux/compat.h>
23#include <linux/anon_inodes.h> 23#include <linux/anon_inodes.h>
24#include <linux/file.h>
24#include <linux/kfifo.h> 25#include <linux/kfifo.h>
25#include <linux/poll.h> 26#include <linux/poll.h>
26#include <linux/timekeeping.h> 27#include <linux/timekeeping.h>
@@ -423,6 +424,7 @@ static int linehandle_create(struct gpio_device *gdev, void __user *ip)
423{ 424{
424 struct gpiohandle_request handlereq; 425 struct gpiohandle_request handlereq;
425 struct linehandle_state *lh; 426 struct linehandle_state *lh;
427 struct file *file;
426 int fd, i, ret; 428 int fd, i, ret;
427 429
428 if (copy_from_user(&handlereq, ip, sizeof(handlereq))) 430 if (copy_from_user(&handlereq, ip, sizeof(handlereq)))
@@ -499,26 +501,41 @@ static int linehandle_create(struct gpio_device *gdev, void __user *ip)
499 i--; 501 i--;
500 lh->numdescs = handlereq.lines; 502 lh->numdescs = handlereq.lines;
501 503
502 fd = anon_inode_getfd("gpio-linehandle", 504 fd = get_unused_fd_flags(O_RDONLY | O_CLOEXEC);
503 &linehandle_fileops,
504 lh,
505 O_RDONLY | O_CLOEXEC);
506 if (fd < 0) { 505 if (fd < 0) {
507 ret = fd; 506 ret = fd;
508 goto out_free_descs; 507 goto out_free_descs;
509 } 508 }
510 509
510 file = anon_inode_getfile("gpio-linehandle",
511 &linehandle_fileops,
512 lh,
513 O_RDONLY | O_CLOEXEC);
514 if (IS_ERR(file)) {
515 ret = PTR_ERR(file);
516 goto out_put_unused_fd;
517 }
518
511 handlereq.fd = fd; 519 handlereq.fd = fd;
512 if (copy_to_user(ip, &handlereq, sizeof(handlereq))) { 520 if (copy_to_user(ip, &handlereq, sizeof(handlereq))) {
513 ret = -EFAULT; 521 /*
514 goto out_free_descs; 522 * fput() will trigger the release() callback, so do not go onto
523 * the regular error cleanup path here.
524 */
525 fput(file);
526 put_unused_fd(fd);
527 return -EFAULT;
515 } 528 }
516 529
530 fd_install(fd, file);
531
517 dev_dbg(&gdev->dev, "registered chardev handle for %d lines\n", 532 dev_dbg(&gdev->dev, "registered chardev handle for %d lines\n",
518 lh->numdescs); 533 lh->numdescs);
519 534
520 return 0; 535 return 0;
521 536
537out_put_unused_fd:
538 put_unused_fd(fd);
522out_free_descs: 539out_free_descs:
523 for (; i >= 0; i--) 540 for (; i >= 0; i--)
524 gpiod_free(lh->descs[i]); 541 gpiod_free(lh->descs[i]);
@@ -721,6 +738,7 @@ static int lineevent_create(struct gpio_device *gdev, void __user *ip)
721 struct gpioevent_request eventreq; 738 struct gpioevent_request eventreq;
722 struct lineevent_state *le; 739 struct lineevent_state *le;
723 struct gpio_desc *desc; 740 struct gpio_desc *desc;
741 struct file *file;
724 u32 offset; 742 u32 offset;
725 u32 lflags; 743 u32 lflags;
726 u32 eflags; 744 u32 eflags;
@@ -815,23 +833,38 @@ static int lineevent_create(struct gpio_device *gdev, void __user *ip)
815 if (ret) 833 if (ret)
816 goto out_free_desc; 834 goto out_free_desc;
817 835
818 fd = anon_inode_getfd("gpio-event", 836 fd = get_unused_fd_flags(O_RDONLY | O_CLOEXEC);
819 &lineevent_fileops,
820 le,
821 O_RDONLY | O_CLOEXEC);
822 if (fd < 0) { 837 if (fd < 0) {
823 ret = fd; 838 ret = fd;
824 goto out_free_irq; 839 goto out_free_irq;
825 } 840 }
826 841
842 file = anon_inode_getfile("gpio-event",
843 &lineevent_fileops,
844 le,
845 O_RDONLY | O_CLOEXEC);
846 if (IS_ERR(file)) {
847 ret = PTR_ERR(file);
848 goto out_put_unused_fd;
849 }
850
827 eventreq.fd = fd; 851 eventreq.fd = fd;
828 if (copy_to_user(ip, &eventreq, sizeof(eventreq))) { 852 if (copy_to_user(ip, &eventreq, sizeof(eventreq))) {
829 ret = -EFAULT; 853 /*
830 goto out_free_irq; 854 * fput() will trigger the release() callback, so do not go onto
855 * the regular error cleanup path here.
856 */
857 fput(file);
858 put_unused_fd(fd);
859 return -EFAULT;
831 } 860 }
832 861
862 fd_install(fd, file);
863
833 return 0; 864 return 0;
834 865
866out_put_unused_fd:
867 put_unused_fd(fd);
835out_free_irq: 868out_free_irq:
836 free_irq(le->irq, le); 869 free_irq(le->irq, le);
837out_free_desc: 870out_free_desc: