lkml.org 
[lkml]   [2022]   [Jun]   [7]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.18 709/879] f2fs: fix to do sanity check on block address in f2fs_do_zero_range()
    Date
    From: Chao Yu <chao@kernel.org>

    commit 25f8236213a91efdf708b9d77e9e51b6fc3e141c upstream.

    As Yanming reported in bugzilla:

    https://bugzilla.kernel.org/show_bug.cgi?id=215894

    I have encountered a bug in F2FS file system in kernel v5.17.

    I have uploaded the system call sequence as case.c, and a fuzzed image can
    be found in google net disk

    The kernel should enable CONFIG_KASAN=y and CONFIG_KASAN_INLINE=y. You can
    reproduce the bug by running the following commands:

    kernel BUG at fs/f2fs/segment.c:2291!
    Call Trace:
    f2fs_invalidate_blocks+0x193/0x2d0
    f2fs_fallocate+0x2593/0x4a70
    vfs_fallocate+0x2a5/0xac0
    ksys_fallocate+0x35/0x70
    __x64_sys_fallocate+0x8e/0xf0
    do_syscall_64+0x3b/0x90
    entry_SYSCALL_64_after_hwframe+0x44/0xae

    The root cause is, after image was fuzzed, block mapping info in inode
    will be inconsistent with SIT table, so in f2fs_fallocate(), it will cause
    panic when updating SIT with invalid blkaddr.

    Let's fix the issue by adding sanity check on block address before updating
    SIT table with it.

    Cc: stable@vger.kernel.org
    Reported-by: Ming Yan <yanming@tju.edu.cn>
    Signed-off-by: Chao Yu <chao.yu@oppo.com>
    Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    ---
    fs/f2fs/file.c | 16 ++++++++++++----
    1 file changed, 12 insertions(+), 4 deletions(-)

    --- a/fs/f2fs/file.c
    +++ b/fs/f2fs/file.c
    @@ -1437,11 +1437,19 @@ static int f2fs_do_zero_range(struct dno
    ret = -ENOSPC;
    break;
    }
    - if (dn->data_blkaddr != NEW_ADDR) {
    - f2fs_invalidate_blocks(sbi, dn->data_blkaddr);
    - dn->data_blkaddr = NEW_ADDR;
    - f2fs_set_data_blkaddr(dn);
    +
    + if (dn->data_blkaddr == NEW_ADDR)
    + continue;
    +
    + if (!f2fs_is_valid_blkaddr(sbi, dn->data_blkaddr,
    + DATA_GENERIC_ENHANCE)) {
    + ret = -EFSCORRUPTED;
    + break;
    }
    +
    + f2fs_invalidate_blocks(sbi, dn->data_blkaddr);
    + dn->data_blkaddr = NEW_ADDR;
    + f2fs_set_data_blkaddr(dn);
    }

    f2fs_update_extent_cache_range(dn, start, 0, index - start);

    \
     
     \ /
      Last update: 2022-06-08 05:13    [W:4.026 / U:0.072 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site