lkml.org 
[lkml]   [2022]   [Apr]   [26]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.19 40/53] ext4: limit length to bitmap_maxbytes - blocksize in punch_hole
    Date
    From: Tadeusz Struk <tadeusz.struk@linaro.org>

    commit 2da376228a2427501feb9d15815a45dbdbdd753e upstream.

    Syzbot found an issue [1] in ext4_fallocate().
    The C reproducer [2] calls fallocate(), passing size 0xffeffeff000ul,
    and offset 0x1000000ul, which, when added together exceed the
    bitmap_maxbytes for the inode. This triggers a BUG in
    ext4_ind_remove_space(). According to the comments in this function
    the 'end' parameter needs to be one block after the last block to be
    removed. In the case when the BUG is triggered it points to the last
    block. Modify the ext4_punch_hole() function and add constraint that
    caps the length to satisfy the one before laster block requirement.

    LINK: [1] https://syzkaller.appspot.com/bug?id=b80bd9cf348aac724a4f4dff251800106d721331
    LINK: [2] https://syzkaller.appspot.com/text?tag=ReproC&x=14ba0238700000

    Fixes: a4bb6b64e39a ("ext4: enable "punch hole" functionality")
    Reported-by: syzbot+7a806094edd5d07ba029@syzkaller.appspotmail.com
    Signed-off-by: Tadeusz Struk <tadeusz.struk@linaro.org>
    Link: https://lore.kernel.org/r/20220331200515.153214-1-tadeusz.struk@linaro.org
    Signed-off-by: Theodore Ts'o <tytso@mit.edu>
    Cc: stable@kernel.org
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    ---
    fs/ext4/inode.c | 11 ++++++++++-
    1 file changed, 10 insertions(+), 1 deletion(-)

    --- a/fs/ext4/inode.c
    +++ b/fs/ext4/inode.c
    @@ -4314,7 +4314,8 @@ int ext4_punch_hole(struct inode *inode,
    struct super_block *sb = inode->i_sb;
    ext4_lblk_t first_block, stop_block;
    struct address_space *mapping = inode->i_mapping;
    - loff_t first_block_offset, last_block_offset;
    + loff_t first_block_offset, last_block_offset, max_length;
    + struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
    handle_t *handle;
    unsigned int credits;
    int ret = 0;
    @@ -4360,6 +4361,14 @@ int ext4_punch_hole(struct inode *inode,
    offset;
    }

    + /*
    + * For punch hole the length + offset needs to be within one block
    + * before last range. Adjust the length if it goes beyond that limit.
    + */
    + max_length = sbi->s_bitmap_maxbytes - inode->i_sb->s_blocksize;
    + if (offset + length > max_length)
    + length = max_length - offset;
    +
    if (offset & (sb->s_blocksize - 1) ||
    (offset + length) & (sb->s_blocksize - 1)) {
    /*

    \
     
     \ /
      Last update: 2022-04-26 10:39    [W:4.269 / U:0.016 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site