• Roman Gushchin's avatar
    fuse: break infinite loop in fuse_fill_write_pages() · 3ca8138f
    Roman Gushchin authored
    I got a report about unkillable task eating CPU. Further
    investigation shows, that the problem is in the fuse_fill_write_pages()
    function. If iov's first segment has zero length, we get an infinite
    loop, because we never reach iov_iter_advance() call.
    
    Fix this by calling iov_iter_advance() before repeating an attempt to
    copy data from userspace.
    
    A similar problem is described in 124d3b70 ("fix writev regression:
    pan hanging unkillable and un-straceable"). If zero-length segmend
    is followed by segment with invalid address,
    iov_iter_fault_in_readable() checks only first segment (zero-length),
    iov_iter_copy_from_user_atomic() skips it, fails at second and
    returns zero -> goto again without skipping zero-length segment.
    
    Patch calls iov_iter_advance() before goto again: we'll skip zero-length
    segment at second iteraction and iov_iter_fault_in_readable() will detect
    invalid address.
    
    Special thanks to Konstantin Khlebnikov, who helped a lot with the commit
    description.
    
    Cc: Andrew Morton <akpm@linux-foundation.org>
    Cc: Maxim Patlasov <mpatlasov@parallels.com>
    Cc: Konstantin Khlebnikov <khlebnikov@yandex-team.ru>
    Signed-off-by: default avatarRoman Gushchin <klamm@yandex-team.ru>
    Signed-off-by: default avatarMiklos Szeredi <miklos@szeredi.hu>
    Fixes: ea9b9907 ("fuse: implement perform_write")
    Cc: <stable@vger.kernel.org>
    3ca8138f
file.c 73.3 KB