• Jan Kara's avatar
    blockdev: Fix livelocks on loop device · 04906b2f
    Jan Kara authored
    bd_set_size() updates also block device's block size. This is somewhat
    unexpected from its name and at this point, only blkdev_open() uses this
    functionality. Furthermore, this can result in changing block size under
    a filesystem mounted on a loop device which leads to livelocks inside
    __getblk_gfp() like:
    Sending NMI from CPU 0 to CPUs 1:
    NMI backtrace for cpu 1
    CPU: 1 PID: 10863 Comm: syz-executor0 Not tainted 4.18.0-rc5+ #151
    Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google
    RIP: 0010:__sanitizer_cov_trace_pc+0x3f/0x50 kernel/kcov.c:106
    Call Trace:
     init_page_buffers+0x3e2/0x530 fs/buffer.c:904
     grow_dev_page fs/buffer.c:947 [inline]
     grow_buffers fs/buffer.c:1009 [inline]
     __getblk_slow fs/buffer.c:1036 [inline]
     __getblk_gfp+0x906/0xb10 fs/buffer.c:1313
     __bread_gfp+0x2d/0x310 fs/buffer.c:1347
     sb_bread include/linux/buffer_head.h:307 [inline]
     fat12_ent_bread+0x14e/0x3d0 fs/fat/fatent.c:75
     fat_ent_read_block fs/fat/fatent.c:441 [inline]
     fat_alloc_clusters+0x8ce/0x16e0 fs/fat/fatent.c:489
     fat_add_cluster+0x7a/0x150 fs/fat/inode.c:101
     __fat_get_block fs/fat/inode.c:148 [inline]
    Trivial reproducer for the problem looks like:
    truncate -s 1G /tmp/image
    losetup /dev/loop0 /tmp/image
    mkfs.ext4 -b 1024 /dev/loop0
    mount -t ext4 /dev/loop0 /mnt
    losetup -c /dev/loop0
    l /mnt
    Fix the problem by moving initialization of a block device block size
    into a separate function and call it when needed.
    Thanks to Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> for help with
    debugging the problem.
    Reported-by: syzbot+9933e4476f365f5d5a1b@syzkaller.appspotmail.com
    Signed-off-by: default avatarJan Kara <jack@suse.cz>
    Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
block_dev.c 54.4 KB