diff options
Diffstat (limited to 'drivers/usb/gadget/function/f_fs.c')
-rw-r--r-- | drivers/usb/gadget/function/f_fs.c | 42 |
1 files changed, 34 insertions, 8 deletions
diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c index 7c6771d027a2..63314ede7ba6 100644 --- a/drivers/usb/gadget/function/f_fs.c +++ b/drivers/usb/gadget/function/f_fs.c | |||
@@ -647,15 +647,26 @@ static void ffs_user_copy_worker(struct work_struct *work) | |||
647 | if (io_data->read && ret > 0) { | 647 | if (io_data->read && ret > 0) { |
648 | int i; | 648 | int i; |
649 | size_t pos = 0; | 649 | size_t pos = 0; |
650 | |||
651 | /* | ||
652 | * Since req->length may be bigger than io_data->len (after | ||
653 | * being rounded up to maxpacketsize), we may end up with more | ||
654 | * data then user space has space for. | ||
655 | */ | ||
656 | ret = min_t(int, ret, io_data->len); | ||
657 | |||
650 | use_mm(io_data->mm); | 658 | use_mm(io_data->mm); |
651 | for (i = 0; i < io_data->nr_segs; i++) { | 659 | for (i = 0; i < io_data->nr_segs; i++) { |
660 | size_t len = min_t(size_t, ret - pos, | ||
661 | io_data->iovec[i].iov_len); | ||
662 | if (!len) | ||
663 | break; | ||
652 | if (unlikely(copy_to_user(io_data->iovec[i].iov_base, | 664 | if (unlikely(copy_to_user(io_data->iovec[i].iov_base, |
653 | &io_data->buf[pos], | 665 | &io_data->buf[pos], len))) { |
654 | io_data->iovec[i].iov_len))) { | ||
655 | ret = -EFAULT; | 666 | ret = -EFAULT; |
656 | break; | 667 | break; |
657 | } | 668 | } |
658 | pos += io_data->iovec[i].iov_len; | 669 | pos += len; |
659 | } | 670 | } |
660 | unuse_mm(io_data->mm); | 671 | unuse_mm(io_data->mm); |
661 | } | 672 | } |
@@ -687,7 +698,7 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data) | |||
687 | struct ffs_epfile *epfile = file->private_data; | 698 | struct ffs_epfile *epfile = file->private_data; |
688 | struct ffs_ep *ep; | 699 | struct ffs_ep *ep; |
689 | char *data = NULL; | 700 | char *data = NULL; |
690 | ssize_t ret, data_len; | 701 | ssize_t ret, data_len = -EINVAL; |
691 | int halt; | 702 | int halt; |
692 | 703 | ||
693 | /* Are we still active? */ | 704 | /* Are we still active? */ |
@@ -787,13 +798,30 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data) | |||
787 | /* Fire the request */ | 798 | /* Fire the request */ |
788 | struct usb_request *req; | 799 | struct usb_request *req; |
789 | 800 | ||
801 | /* | ||
802 | * Sanity Check: even though data_len can't be used | ||
803 | * uninitialized at the time I write this comment, some | ||
804 | * compilers complain about this situation. | ||
805 | * In order to keep the code clean from warnings, data_len is | ||
806 | * being initialized to -EINVAL during its declaration, which | ||
807 | * means we can't rely on compiler anymore to warn no future | ||
808 | * changes won't result in data_len being used uninitialized. | ||
809 | * For such reason, we're adding this redundant sanity check | ||
810 | * here. | ||
811 | */ | ||
812 | if (unlikely(data_len == -EINVAL)) { | ||
813 | WARN(1, "%s: data_len == -EINVAL\n", __func__); | ||
814 | ret = -EINVAL; | ||
815 | goto error_lock; | ||
816 | } | ||
817 | |||
790 | if (io_data->aio) { | 818 | if (io_data->aio) { |
791 | req = usb_ep_alloc_request(ep->ep, GFP_KERNEL); | 819 | req = usb_ep_alloc_request(ep->ep, GFP_KERNEL); |
792 | if (unlikely(!req)) | 820 | if (unlikely(!req)) |
793 | goto error_lock; | 821 | goto error_lock; |
794 | 822 | ||
795 | req->buf = data; | 823 | req->buf = data; |
796 | req->length = io_data->len; | 824 | req->length = data_len; |
797 | 825 | ||
798 | io_data->buf = data; | 826 | io_data->buf = data; |
799 | io_data->ep = ep->ep; | 827 | io_data->ep = ep->ep; |
@@ -815,7 +843,7 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data) | |||
815 | 843 | ||
816 | req = ep->req; | 844 | req = ep->req; |
817 | req->buf = data; | 845 | req->buf = data; |
818 | req->length = io_data->len; | 846 | req->length = data_len; |
819 | 847 | ||
820 | req->context = &done; | 848 | req->context = &done; |
821 | req->complete = ffs_epfile_io_complete; | 849 | req->complete = ffs_epfile_io_complete; |
@@ -2663,8 +2691,6 @@ static inline struct f_fs_opts *ffs_do_functionfs_bind(struct usb_function *f, | |||
2663 | func->conf = c; | 2691 | func->conf = c; |
2664 | func->gadget = c->cdev->gadget; | 2692 | func->gadget = c->cdev->gadget; |
2665 | 2693 | ||
2666 | ffs_data_get(func->ffs); | ||
2667 | |||
2668 | /* | 2694 | /* |
2669 | * in drivers/usb/gadget/configfs.c:configfs_composite_bind() | 2695 | * in drivers/usb/gadget/configfs.c:configfs_composite_bind() |
2670 | * configurations are bound in sequence with list_for_each_entry, | 2696 | * configurations are bound in sequence with list_for_each_entry, |