mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Chao Yu <chao@kernel.org>
To: Dmitriy Chumachenko <Dmitry.Chumachenko@cyberprotect.ru>,
	Jaegeuk Kim <jaegeuk@kernel.org>
Cc: chao@kernel.org, linux-f2fs-devel@lists.sourceforge.net,
	linux-kernel@vger.kernel.org, lvc-project@linuxtesting.org,
	syzbot+8b85865808c8908a0d8c@syzkaller.appspotmail.com
Subject: Re: [PATCH] f2fs: reject mount when block_count exceeds device capacity
Date: Mon, 2 Nov 2026 11:05:52 +0800	[thread overview]
Message-ID: <6b95dd7b-4e49-4c7d-a3d2-70341e183289@kernel.org> (raw)
In-Reply-To: <20261030111112.20953-1-Dmitry.Chumachenko@cyberprotect.ru>

On 10/30/26 19:11, Dmitriy Chumachenko wrote:
> During fuzz testing, the following issue was discovered.
> 
> INFO: task kworker/u9:2:981 blocked for more than 122 seconds.
>        Not tainted 7.1.0-rc4-00103-ge94869f14310 #59
> "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
> task:kworker/u9:2    state:D stack:25800 pid:981   tgid:981   ppid:2      task_flags:0x4208060 flags:0x00080000
> Workqueue: writeback wb_workfn (flush-7:0)
> Call Trace:
>   <TASK>
>   __schedule+0x122f/0x6530
>   rt_mutex_schedule+0x96/0xe0
>   __rt_mutex_slowlock_locked.constprop.0+0x13bd/0x3280
>   rwbase_write_lock+0x5df/0x720
>   f2fs_down_write_trace+0xc8/0x320
>   f2fs_balance_fs+0x6ee/0xa50
>   f2fs_write_inode+0x5e4/0x15a0
>   __writeback_single_inode+0xcda/0x1360
>   writeback_sb_inodes+0x767/0x1d90
>   __writeback_inodes_wb+0xf8/0x2d0
>   wb_writeback+0x723/0xb90
>   wb_workfn+0x8e6/0xc10
>   process_one_work+0xa0e/0x1980
>   worker_thread+0x5ef/0xe50
>   kthread+0x370/0x450
>   ret_from_fork+0x72b/0xd50
>   ret_from_fork_asm+0x1a/0x30
>   </TASK>
> 
> The superblock declares a block_count larger than the backing device, but
> sanity_check_raw_super() validates block_count only against segment_count
> and never against the device size, so the oversized filesystem mounts and
> its main area extends past the end of the device.
> 
> On the first fallocate(), f2fs_balance_fs() runs foreground GC, which
> selects a victim segment located beyond the device. The blocks are valid
> per on-disk metadata, so is_alive() accepts them and do_garbage_collect()
> keeps issuing reads past the end of the device without making progress,
> while holding sbi->gc_lock. Writeback and sync then block on gc_lock
> indefinitely, producing the hung task above.
> 
> This only affects single-device setups: on a multi-device volume
> block_count is the whole-filesystem total and legitimately exceeds the
> primary device, so the check is restricted to single-device images and
> compares block_count against the backing device capacity.
> 
> Fixes: aff063e266cb ("f2fs: add super block operations")
> Reported-by: syzbot+8b85865808c8908a0d8c@syzkaller.appspotmail.com
> Closes: https://syzkaller.appspot.com/bug?extid=8b85865808c8908a0d8c
> Signed-off-by: Dmitriy Chumachenko <Dmitry.Chumachenko@cyberprotect.ru>
> ---
>   fs/f2fs/super.c | 7 +++++++
>   1 file changed, 7 insertions(+)
> 
> diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
> index fabcafafabf1..ba484a32f292 100644
> --- a/fs/f2fs/super.c
> +++ b/fs/f2fs/super.c
> @@ -3445,6 +3445,13 @@ static int sanity_check_raw_super(struct f2fs_sb_info *sbi,
>   			  segment_count, le64_to_cpu(raw_super->block_count));
>   		return -EFSCORRUPTED;
>   	}
> +	if (!RDEV(0).path[0] &&

It needs to cover multiple device case as well? can you please do that?

> +	    le64_to_cpu(raw_super->block_count) > sb_bdev_nr_blocks(sbi->sb)) {

static inline u64 sb_bdev_nr_blocks(struct super_block *sb)
{
	return bdev_nr_sectors(sb->s_bdev) >>
		(sb->s_blocksize_bits - SECTOR_SHIFT);
}

- f2fs_fill_super
  - read_raw_super_block
   - sanity_check_raw_super
    - sb_bdev_nr_blocks
    : access s_blocksize_bits
  - sb_set_blocksize
  : update s_blocksize_bits

So, update like this?

	u64 dev_blocks = bdev_nr_bytes(sbi->sb->s_bdev) >>
			le32_to_cpu(raw_super->log_blocksize);

	if (le64_to_cpu(raw_super->block_count) > dev_blocks) {
		f2fs_info(sbi, "block_count (%llu) exceeds device size (%llu blocks)",
		le64_to_cpu(raw_super->block_count), dev_blocks);
		return -EFSCORRUPTED;
	}

Thanks,

> +		f2fs_info(sbi, "block_count(%llu) exceeds device capacity(%llu blocks)",
> +			  le64_to_cpu(raw_super->block_count),
> +			  (unsigned long long)sb_bdev_nr_blocks(sbi->sb));
> +		return -EFSCORRUPTED;
> +	}
>   
>   	if (RDEV(0).path[0]) {
>   		block_t dev_seg_count = le32_to_cpu(RDEV(0).total_segments);


      reply	other threads:[~2026-11-02  3:05 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-30 11:11 Dmitriy Chumachenko
2026-11-02  3:05 ` Chao Yu [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=6b95dd7b-4e49-4c7d-a3d2-70341e183289@kernel.org \
    --to=chao@kernel.org \
    --cc=Dmitry.Chumachenko@cyberprotect.ru \
    --cc=jaegeuk@kernel.org \
    --cc=linux-f2fs-devel@lists.sourceforge.net \
    --cc=linux-kernel@vger.kernel.org \
    --cc=lvc-project@linuxtesting.org \
    --cc=syzbot+8b85865808c8908a0d8c@syzkaller.appspotmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®