* [PATCH] f2fs: reject mount when block_count exceeds device capacity
@ 2026-10-30 11:11 Dmitriy Chumachenko
2026-11-02 3:05 ` Chao Yu
0 siblings, 1 reply; 2+ messages in thread
From: Dmitriy Chumachenko @ 2026-10-30 11:11 UTC (permalink / raw)
To: Jaegeuk Kim
Cc: Chao Yu, linux-f2fs-devel, linux-kernel, lvc-project,
Dmitriy Chumachenko, syzbot+8b85865808c8908a0d8c
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] &&
+ le64_to_cpu(raw_super->block_count) > sb_bdev_nr_blocks(sbi->sb)) {
+ 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);
--
2.49.0
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: [PATCH] f2fs: reject mount when block_count exceeds device capacity
2026-10-30 11:11 [PATCH] f2fs: reject mount when block_count exceeds device capacity Dmitriy Chumachenko
@ 2026-11-02 3:05 ` Chao Yu
0 siblings, 0 replies; 2+ messages in thread
From: Chao Yu @ 2026-11-02 3:05 UTC (permalink / raw)
To: Dmitriy Chumachenko, Jaegeuk Kim
Cc: chao, linux-f2fs-devel, linux-kernel, lvc-project,
syzbot+8b85865808c8908a0d8c
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);
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-11-02 3:05 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-30 11:11 [PATCH] f2fs: reject mount when block_count exceeds device capacity Dmitriy Chumachenko
2026-11-02 3:05 ` Chao Yu
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®