• Theodore Ts'o's avatar
    ext4: avoid possible overflow in ext4_map_blocks() · e861b5e9
    Theodore Ts'o authored
    The ext4_map_blocks() function returns the number of blocks which
    satisfying the caller's request.  This number of blocks requested by
    the caller is specified by an unsigned integer, but the return value
    of ext4_map_blocks() is a signed integer (to accomodate error codes
    per the kernel's standard error signalling convention).
    
    Historically, overflows could never happen since mballoc() will refuse
    to allocate more than 2048 blocks at a time (which is something we
    should fix), and if the blocks were already allocated, the fact that
    there would be some number of intervening metadata blocks pretty much
    guaranteed that there could never be a contiguous region of data
    blocks that was greater than 2**31 blocks.
    
    However, this is now possible if there is a file system which is a bit
    bigger than 8TB, and is created using the new mke2fs hugeblock
    feature, which can create a perfectly contiguous file.  In that case,
    if a userspace program attempted to call fallocate() on this already
    fully allocated file, it's possible that ext4_map_blocks() could
    return a number large enough that it would overflow a signed integer,
    resulting in a ext4 thinking that the ext4_map_blocks() call had
    failed with some strange error code.
    
    Since ext4_map_blocks() is always free to return a smaller number of
    blocks than what was requested by the caller, fix this by capping the
    number of blocks that ext4_map_blocks() will ever try to map to 2**31
    - 1.  In practice this should never get hit, except by someone
    deliberately trying to provke the above-described bug.
    
    Thanks to the PaX team for asking whethre this could possibly happen
    in some off-line discussions about using some static code checking
    technology they are developing to find bugs in kernel code.
    Signed-off-by: default avatar"Theodore Ts'o" <tytso@mit.edu>
    e861b5e9
inode.c 150 KB