Re: [PATCH] usb: gadget: f_fs: Fix incorrect EFAULT generation for async read operations

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 03/28/2016 04:28 PM, Al Viro wrote:
> On Mon, Mar 28, 2016 at 02:42:43PM +0200, Lars-Peter Clausen wrote:
>> 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 attempt to copy that many bytes using
>> copy_to_user(). If copy_to_user() returned less copied bytes the code would
>> generate a EFAULT error. This has exactly the same behaviour as using
>> copy_to_iter() except that copy_to_iter() can't fail since the check
>> whether access to the user supplied buffer is OK is already done earlier
>> and copy_to_iter() wont be called in that case. Restore the original
>> behaviour by simply dropping the code that generates the EFAULT error.
> 
> "The check whether access to user supplied buffer is OK" is *not* done
> before.  access_ok() checked does not guarantee that copy_to_user() won't
> fail.
> 
> access_ok() and its equivalents checks only one thing - that you are not
> trying to pass kernel addresses for userland ones.  It does not check
> permissions you have for individual pages, it does not check if they are
> present, or, if absent, that page fault will bring them in.
> 
> Both copy_to_user() and copy_to_iter() can bloody well fail halfway through
> without access_ok() having any objections.

Hm, right. I guess I got confused on the copy_to_iter() case since it
can't fail when copying into kernel buffers. It would have be nice if
the semantics of all those iov iter functions had been documented.

>  E.g. do read() into an mmapped buffer, with one page somewhere in the
> middle munmapped.  Or the first page munmapped, for that matter...

Yeah, I actually wondered how that could possibly work...

> 
> I see where the commit in question is buggy, but your patch doesn't really
> fix it; original behaviour is not restored.
> 
> -                                       ret = min_t(size_t, ret, io_data->len);
> -
> -                                       if (unlikely(copy_to_user(io_data->buf,
> -                                               data, ret)))
> +                                       ret = copy_to_iter(data, ret, &io_data->data);
> +                                       if (unlikely(iov_iter_count(&io_data->data)))
>                                                 ret = -EFAULT;
> 
> was wrong; what it should've done to preserve the original behaviour is
> something like
> 			copied = copy_to_iter(data, ret, &io_data->data)
> 			if (unlikely(copied != ret))
> 				ret = iov_iter_count(&io_data->data)
> 					? EFAULT : copied;
> 
> After copy_to_iter(data, len, target) we could have three outcomes:
> 	* everything copied; return value is equal to len
> 	* copying stopped at the end of iterator; return value is less than len,
> iov_iter_count(target) is zero.
> 	* copying stopped at unmapped page/page that was readonly/etc;
> return value is less than len, iov_iter_count(target) is *not* zero.

Yes. It's a bit of a shame that the copy_{to,from}_iter() functions
don't allow you to easily distinguish between target buffer is to small
and a fault occurred mid way through. This can't be the only place which
wants to know this.
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux