summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKaixuan Li <kaixuanli0131@gmail.com>2026-09-19 00:55:07 +0800
committerJaegeuk Kim <jaegeuk@kernel.org>2026-10-13 18:45:03 +0000
commit9c4ee79190c8c23a9fb5c07d3bc87eaac514b2bb (patch)
tree8a63231415ed943946632ac102596e042e1fe070
parentc04f209773ecb31e592cababce0d6658ee0b8d58 (diff)
downloadlinux-next-9c4ee79190c8c23a9fb5c07d3bc87eaac514b2bb.tar.gz
linux-next-9c4ee79190c8c23a9fb5c07d3bc87eaac514b2bb.zip
f2fs: check every cur_*_segno[] entry on readonly images
sanity_check_ckpt() bounds-checks cur_node_segno[] and cur_data_segno[] against main_segs, but on an image with the RO feature the goto that skips the duplicate-segno cross-checks also leaves the enclosing loop, so only index 0 of each array is ever checked. An unchecked index reaches __set_sit_entry_type() through build_curseg() -> reset_curseg(), which writes se->type through &sit_i->sentries[segno]. With segment_count_main 120 and cur_data_segno[1] set to 200, KASAN reports three out-of-bounds writes during mount and the mount then succeeds. Use continue so every index is bounds-checked, and skip the node-vs-data cross-check explicitly, which is the other thing the old goto skipped. Cc: stable@kernel.org Fixes: a7d9fe3c3388 ("f2fs: support RO feature") Signed-off-by: Kaixuan Li <kaixuanli0131@gmail.com> Reviewed-by: Chao Yu <chao@kernel.org> Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
-rw-r--r--fs/f2fs/super.c9
1 files changed, 6 insertions, 3 deletions
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index 2b9213db2c0f..17aae65e750e 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -4336,7 +4336,7 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi)
return 1;
if (f2fs_sb_has_readonly(sbi))
- goto check_data;
+ continue;
for (j = i + 1; j < NR_CURSEG_NODE_TYPE; j++) {
if (le32_to_cpu(ckpt->cur_node_segno[i]) ==
@@ -4348,14 +4348,14 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi)
}
}
}
-check_data:
+
for (i = 0; i < NR_CURSEG_DATA_TYPE; i++) {
if (le32_to_cpu(ckpt->cur_data_segno[i]) >= main_segs ||
le16_to_cpu(ckpt->cur_data_blkoff[i]) >= blocks_per_seg)
return 1;
if (f2fs_sb_has_readonly(sbi))
- goto skip_cross;
+ continue;
for (j = i + 1; j < NR_CURSEG_DATA_TYPE; j++) {
if (le32_to_cpu(ckpt->cur_data_segno[i]) ==
@@ -4367,6 +4367,9 @@ check_data:
}
}
}
+ if (f2fs_sb_has_readonly(sbi))
+ goto skip_cross;
+
for (i = 0; i < NR_CURSEG_NODE_TYPE; i++) {
for (j = 0; j < NR_CURSEG_DATA_TYPE; j++) {
if (le32_to_cpu(ckpt->cur_node_segno[i]) ==