• David Howells's avatar
    afs: Don't unlock fetched data pages until the op completes successfully · 9d1be4f4
    David Howells authored
    Don't call req->page_done() on each page as we finish filling it with
    the data coming from the network.  Whilst this might speed up the
    application a bit, it's a problem if there's a network failure and the
    operation has to be reissued.
    
    If this happens, an oops occurs because afs_readpages_page_done() clears
    the pointer to each page it unlocks and when a retry happens, the
    pointers to the pages it wants to fill are now NULL (and the pages have
    been unlocked anyway).
    
    Instead, wait till the operation completes successfully and only then
    release all the pages after clearing any terminal gap (the server can
    give us less data than we requested as we're allowed to ask for more
    than is available).
    
    KASAN produces a bug like the following, and even without KASAN, it can
    oops and panic.
    
        BUG: KASAN: wild-memory-access in _copy_to_iter+0x323/0x5f4
        Write of size 1404 at addr 0005088000000000 by task md5sum/5235
    
        CPU: 0 PID: 5235 Comm: md5sum Not tainted 5.7.0-rc3-fscache+ #250
        Hardware name: ASUS All Series/H97-PLUS, BIOS 2306 10/09/2014
        Call Trace:
         memcpy+0x39/0x58
         _copy_to_iter+0x323/0x5f4
         __skb_datagram_iter+0x89/0x2a6
         skb_copy_datagram_iter+0x129/0x135
         rxrpc_recvmsg_data.isra.0+0x615/0xd42
         rxrpc_kernel_recv_data+0x1e9/0x3ae
         afs_extract_data+0x139/0x33a
         yfs_deliver_fs_fetch_data64+0x47a/0x91b
         afs_deliver_to_call+0x304/0x709
         afs_wait_for_call_to_complete+0x1cc/0x4ad
         yfs_fs_fetch_data+0x279/0x288
         afs_fetch_data+0x1e1/0x38d
         afs_readpages+0x593/0x72e
         read_pages+0xf5/0x21e
         __do_page_cache_readahead+0x128/0x23f
         ondemand_readahead+0x36e/0x37f
         generic_file_buffered_read+0x234/0x680
         new_sync_read+0x109/0x17e
         vfs_read+0xe6/0x138
         ksys_read+0xd8/0x14d
         do_syscall_64+0x6e/0x8a
         entry_SYSCALL_64_after_hwframe+0x49/0xb3
    
    Fixes: 196ee9cd ("afs: Make afs_fs_fetch_data() take a list of pages")
    Fixes: 30062bd1 ("afs: Implement YFS support in the fs client")
    Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
    Reviewed-by: default avatarMatthew Wilcox (Oracle) <willy@infradead.org>
    Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
    9d1be4f4
yfsclient.c 53.9 KB