lkml.org 
[lkml]   [2022]   [Oct]   [24]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.10 051/390] f2fs: fix to do sanity check on destination blkaddr during recovery
    Date
    From: Chao Yu <chao@kernel.org>

    commit 0ef4ca04a3f9223ff8bc440041c524b2123e09a3 upstream.

    As Wenqing Liu reported in bugzilla:

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

    loop5: detected capacity change from 0 to 131072
    F2FS-fs (loop5): recover_inode: ino = 6, name = hln, inline = 1
    F2FS-fs (loop5): recover_data: ino = 6 (i_size: recover) err = 0
    F2FS-fs (loop5): recover_inode: ino = 6, name = hln, inline = 1
    F2FS-fs (loop5): recover_data: ino = 6 (i_size: recover) err = 0
    F2FS-fs (loop5): recover_inode: ino = 6, name = hln, inline = 1
    F2FS-fs (loop5): recover_data: ino = 6 (i_size: recover) err = 0
    F2FS-fs (loop5): Bitmap was wrongly set, blk:5634
    ------------[ cut here ]------------
    WARNING: CPU: 3 PID: 1013 at fs/f2fs/segment.c:2198
    RIP: 0010:update_sit_entry+0xa55/0x10b0 [f2fs]
    Call Trace:
    <TASK>
    f2fs_do_replace_block+0xa98/0x1890 [f2fs]
    f2fs_replace_block+0xeb/0x180 [f2fs]
    recover_data+0x1a69/0x6ae0 [f2fs]
    f2fs_recover_fsync_data+0x120d/0x1fc0 [f2fs]
    f2fs_fill_super+0x4665/0x61e0 [f2fs]
    mount_bdev+0x2cf/0x3b0
    legacy_get_tree+0xed/0x1d0
    vfs_get_tree+0x81/0x2b0
    path_mount+0x47e/0x19d0
    do_mount+0xce/0xf0
    __x64_sys_mount+0x12c/0x1a0
    do_syscall_64+0x38/0x90
    entry_SYSCALL_64_after_hwframe+0x63/0xcd

    If we enable CONFIG_F2FS_CHECK_FS config, it will trigger a kernel panic
    instead of warning.

    The root cause is: in fuzzed image, SIT table is inconsistent with inode
    mapping table, result in triggering such warning during SIT table update.

    This patch introduces a new flag DATA_GENERIC_ENHANCE_UPDATE, w/ this
    flag, data block recovery flow can check destination blkaddr's validation
    in SIT table, and skip f2fs_replace_block() to avoid inconsistent status.

    Cc: stable@vger.kernel.org
    Reported-by: Wenqing Liu <wenqingliu0120@gmail.com>
    Signed-off-by: Chao Yu <chao@kernel.org>
    Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    ---
    fs/f2fs/checkpoint.c | 10 +++++++++-
    fs/f2fs/f2fs.h | 4 ++++
    fs/f2fs/recovery.c | 8 ++++++++
    3 files changed, 21 insertions(+), 1 deletion(-)

    --- a/fs/f2fs/checkpoint.c
    +++ b/fs/f2fs/checkpoint.c
    @@ -136,7 +136,7 @@ static bool __is_bitmap_valid(struct f2f
    unsigned int segno, offset;
    bool exist;

    - if (type != DATA_GENERIC_ENHANCE && type != DATA_GENERIC_ENHANCE_READ)
    + if (type == DATA_GENERIC)
    return true;

    segno = GET_SEGNO(sbi, blkaddr);
    @@ -144,6 +144,13 @@ static bool __is_bitmap_valid(struct f2f
    se = get_seg_entry(sbi, segno);

    exist = f2fs_test_bit(offset, se->cur_valid_map);
    + if (exist && type == DATA_GENERIC_ENHANCE_UPDATE) {
    + f2fs_err(sbi, "Inconsistent error blkaddr:%u, sit bitmap:%d",
    + blkaddr, exist);
    + set_sbi_flag(sbi, SBI_NEED_FSCK);
    + return exist;
    + }
    +
    if (!exist && type == DATA_GENERIC_ENHANCE) {
    f2fs_err(sbi, "Inconsistent error blkaddr:%u, sit bitmap:%d",
    blkaddr, exist);
    @@ -181,6 +188,7 @@ bool f2fs_is_valid_blkaddr(struct f2fs_s
    case DATA_GENERIC:
    case DATA_GENERIC_ENHANCE:
    case DATA_GENERIC_ENHANCE_READ:
    + case DATA_GENERIC_ENHANCE_UPDATE:
    if (unlikely(blkaddr >= MAX_BLKADDR(sbi) ||
    blkaddr < MAIN_BLKADDR(sbi))) {
    f2fs_warn(sbi, "access invalid blkaddr:%u",
    --- a/fs/f2fs/f2fs.h
    +++ b/fs/f2fs/f2fs.h
    @@ -235,6 +235,10 @@ enum {
    * condition of read on truncated area
    * by extent_cache
    */
    + DATA_GENERIC_ENHANCE_UPDATE, /*
    + * strong check on range and segment
    + * bitmap for update case
    + */
    META_GENERIC,
    };

    --- a/fs/f2fs/recovery.c
    +++ b/fs/f2fs/recovery.c
    @@ -661,6 +661,14 @@ retry_prev:
    goto err;
    }

    + if (f2fs_is_valid_blkaddr(sbi, dest,
    + DATA_GENERIC_ENHANCE_UPDATE)) {
    + f2fs_err(sbi, "Inconsistent dest blkaddr:%u, ino:%lu, ofs:%u",
    + dest, inode->i_ino, dn.ofs_in_node);
    + err = -EFSCORRUPTED;
    + goto err;
    + }
    +
    /* write dummy data page */
    f2fs_replace_block(sbi, &dn, src, dest,
    ni.version, false, false);

    \
     
     \ /
      Last update: 2022-10-24 15:08    [W:4.029 / U:0.984 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site