Hi Al, Lars-Peter Clausen <lars@xxxxxxxxxx> writes: > In the current implementation functionfs generates a EFAULT for async read > operations if the read buffer size is larger than the URB data size. Since > a application does not necessarily know how much data the host side is > going to send it typically supplies a buffer larger than the actual data, > which will then result in a EFAULT error. > > This behaviour was introduced while refactoring the code to use iov_iter > interface in commit c993c39b8639 ("gadget/function/f_fs.c: use put iov_iter > into io_data"). The original code took the minimum over the URB size and > the user buffer size and then attempted to copy that many bytes using > copy_to_user(). If copy_to_user() could not copy all data a EFAULT error > was generated. Restore the original behaviour by only generating a EFAULT > error when the number of bytes copied is not the size of the URB and the > target buffer has not been fully filled. > > Commit 342f39a6c8d3 ("usb: gadget: f_fs: fix check in read operation") > already fixed the same problem for the synchronous read path. > > Fixes: c993c39b8639 ("gadget/function/f_fs.c: use put iov_iter into io_data") > Signed-off-by: Lars-Peter Clausen <lars@xxxxxxxxxx> > --- > Changes since v1: > * copy_to_iter() can fail, make sure that is handled. Test this case by > mapping part of the target buffer read-only. > > Signed-off-by: Lars-Peter Clausen <lars@xxxxxxxxxx> > --- > drivers/usb/gadget/function/f_fs.c | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c > index 8cfce10..3b27aa0 100644 > --- a/drivers/usb/gadget/function/f_fs.c > +++ b/drivers/usb/gadget/function/f_fs.c > @@ -650,7 +650,7 @@ static void ffs_user_copy_worker(struct work_struct *work) > if (io_data->read && ret > 0) { > use_mm(io_data->mm); > ret = copy_to_iter(io_data->buf, ret, &io_data->data); > - if (iov_iter_count(&io_data->data)) > + if (ret != io_data->req->actual && iov_iter_count(&io_data->data)) > ret = -EFAULT; > unuse_mm(io_data->mm); > } does this look good for you now ? -- balbi
Attachment:
signature.asc
Description: PGP signature