• B
    xfs: flush new eof page on truncate to avoid post-eof corruption · 869ae85d
    Brian Foster 提交于
    It is possible to expose non-zeroed post-EOF data in XFS if the new
    EOF page is dirty, backed by an unwritten block and the truncate
    happens to race with writeback. iomap_truncate_page() will not zero
    the post-EOF portion of the page if the underlying block is
    unwritten. The subsequent call to truncate_setsize() will, but
    doesn't dirty the page. Therefore, if writeback happens to complete
    after iomap_truncate_page() (so it still sees the unwritten block)
    but before truncate_setsize(), the cached page becomes inconsistent
    with the on-disk block. A mapped read after the associated page is
    reclaimed or invalidated exposes non-zero post-EOF data.
    
    For example, consider the following sequence when run on a kernel
    modified to explicitly flush the new EOF page within the race
    window:
    
    $ xfs_io -fc "falloc 0 4k" -c fsync /mnt/file
    $ xfs_io -c "pwrite 0 4k" -c "truncate 1k" /mnt/file
      ...
    $ xfs_io -c "mmap 0 4k" -c "mread -v 1k 8" /mnt/file
    00000400:  00 00 00 00 00 00 00 00  ........
    $ umount /mnt/; mount <dev> /mnt/
    $ xfs_io -c "mmap 0 4k" -c "mread -v 1k 8" /mnt/file
    00000400:  cd cd cd cd cd cd cd cd  ........
    
    Update xfs_setattr_size() to explicitly flush the new EOF page prior
    to the page truncate to ensure iomap has the latest state of the
    underlying block.
    
    Fixes: 68a9f5e7 ("xfs: implement iomap based buffered write path")
    Signed-off-by: NBrian Foster <bfoster@redhat.com>
    Reviewed-by: NDarrick J. Wong <darrick.wong@oracle.com>
    Signed-off-by: NDarrick J. Wong <darrick.wong@oracle.com>
    869ae85d
xfs_iops.c 34.7 KB