On 2/6/20 11:40 PM, Miklos Szeredi wrote:
On Thu, Feb 6, 2020 at 1:33 PM Xiao Yang <ice_yangxiao@xxxxxxx> wrote:
On 2/6/20 8:14 PM, Miklos Szeredi wrote:
On Wed, Feb 5, 2020 at 3:37 PM Miklos Szeredi <miklos@xxxxxxxxxx> wrote:
On Mon, Feb 3, 2020 at 8:37 AM Xiao Yang <ice_yangxiao@xxxxxxx> wrote:
Buffered read in fuse normally goes via:
-> generic_file_buffered_read()
------------------------------
-> fuse_readpages()
-> fuse_send_readpages()
or
-> fuse_readpage() [if fuse_readpages() fails to get page]
-> fuse_do_readpage()
------------------------------
-> fuse_simple_request()
Buffered read changes original offset to page-aligned length by left-shift
and extends original count to be multiples of PAGE_SIZE and then fuse
forwards these new parameters to a userspace process, so it is possible
for the resulting offset(e.g page-aligned offset + extended count) to
exceed the whole file size(even the max value of off_t) when the userspace
process does read with new parameters.
xfstests generic/525 gets "pread: Invalid argument" error on virtiofs
because it triggers this issue. See the following explanation:
PAGE_SIZE: 4096, file size: 2^63 - 1
Original: offset: 2^63 - 2, count: 1
Changed by buffered read: offset: 2^63 - 4096, count: 4096
New offset + new count exceeds the file size as well as LLONG_MAX
Thanks for the report and analysis.
However this patch may corrupt the cache if i_size changes between
calls to fuse_page_length(). (e.g. first page length set to 33;
second page length to 45; then 33-4095 will be zeroed and 4096-4140
will be filled from offset 33-77). This will be mitigated by the
pages being invalidated when i_size changes
(fuse_change_attributes()). Filling the pages with wrong data is not
a good idea regardless.
I think the best approach is first to just fix the xfstest reported
bug by clamping the end offset to LLONG_MAX. That's a simple patch,
independent of i_size, and hence trivial to verify and hard to mess
up.
Applied a fix and pushed to:
git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/fuse.git#for-next
Hi Miklos,
Sorry for the late reply.
You have applied a fix quickly when I am going to send a patch today.
Just one comment for your fix:
I think we need to add the overflow check in fuse_send_readpages() and
fuse_do_readpage().
Because generic_file_buffered_read() will call fuse_readpage() if
fuse_readpages() fails to get page.
Thanks, fixed.
Hi Miklos,
Thanks a lot for your quick fix again. :-)
I have tested your patch and it works fine.
Reviewed-by: Xiao Yang <ice_yangxiao@xxxxxxx>
Thanks,
Xiao Yang
Miklos