This patch addresses an open issue of buffer overflow in f2fs function stat_show(). On the off chance that si->sbi->s_flag had one of its bits (on the higher end) set to 1, for_each_set_bit() will loop more than s_flag[] can afford, leading in turn to erroneous array access.
The issue in question has been fixed in commit 5bb9c111cd98 ("f2fs: convert to MAX_SBI_FLAG instead of 32 in stat_show()") and cherry-picked for 6.1 stable branch.
Modified patch can now be cleanly applied to linux-6.1.y. All of the changes made to the patch in order to adapt it are described at the end of commit message in [PATCH 6.1 1/1] f2fs: convert to MAX_SBI_FLAG instead of 32 in stat_show().
From: Yangtao Li frank.li@vivo.com
commit 5bb9c111cd98ad844d48ace9924e29f56312f036 upstream.
BIW reduce the s_flag array size and make s_flag constant.
Signed-off-by: Yangtao Li frank.li@vivo.com Reviewed-by: Chao Yu chao@kernel.org Signed-off-by: Jaegeuk Kim jaegeuk@kernel.org [Nikita: This patch has been cherry-picked from original commit: the only discrepancy was in stat_show(). Specifically, due to lack of commit dda7d77bcd42 ("f2fs: replace si->sbi w/ sbi in stat_show()") keep &si->sbi->s_flag instead of &sbi->s_flag.] Signed-off-by: Nikita Zhandarovich n.zhandarovich@fintech.ru --- fs/f2fs/debug.c | 36 ++++++++++++++++++------------------ fs/f2fs/f2fs.h | 6 +++++- 2 files changed, 23 insertions(+), 19 deletions(-)
diff --git a/fs/f2fs/debug.c b/fs/f2fs/debug.c index a9baa121d829..002bf12b4e26 100644 --- a/fs/f2fs/debug.c +++ b/fs/f2fs/debug.c @@ -332,22 +332,22 @@ static void update_mem_info(struct f2fs_sb_info *sbi) #endif }
-static char *s_flag[] = { - [SBI_IS_DIRTY] = " fs_dirty", - [SBI_IS_CLOSE] = " closing", - [SBI_NEED_FSCK] = " need_fsck", - [SBI_POR_DOING] = " recovering", - [SBI_NEED_SB_WRITE] = " sb_dirty", - [SBI_NEED_CP] = " need_cp", - [SBI_IS_SHUTDOWN] = " shutdown", - [SBI_IS_RECOVERED] = " recovered", - [SBI_CP_DISABLED] = " cp_disabled", - [SBI_CP_DISABLED_QUICK] = " cp_disabled_quick", - [SBI_QUOTA_NEED_FLUSH] = " quota_need_flush", - [SBI_QUOTA_SKIP_FLUSH] = " quota_skip_flush", - [SBI_QUOTA_NEED_REPAIR] = " quota_need_repair", - [SBI_IS_RESIZEFS] = " resizefs", - [SBI_IS_FREEZING] = " freezefs", +static const char *s_flag[MAX_SBI_FLAG] = { + [SBI_IS_DIRTY] = "fs_dirty", + [SBI_IS_CLOSE] = "closing", + [SBI_NEED_FSCK] = "need_fsck", + [SBI_POR_DOING] = "recovering", + [SBI_NEED_SB_WRITE] = "sb_dirty", + [SBI_NEED_CP] = "need_cp", + [SBI_IS_SHUTDOWN] = "shutdown", + [SBI_IS_RECOVERED] = "recovered", + [SBI_CP_DISABLED] = "cp_disabled", + [SBI_CP_DISABLED_QUICK] = "cp_disabled_quick", + [SBI_QUOTA_NEED_FLUSH] = "quota_need_flush", + [SBI_QUOTA_SKIP_FLUSH] = "quota_skip_flush", + [SBI_QUOTA_NEED_REPAIR] = "quota_need_repair", + [SBI_IS_RESIZEFS] = "resizefs", + [SBI_IS_FREEZING] = "freezefs", };
static int stat_show(struct seq_file *s, void *v) @@ -367,8 +367,8 @@ static int stat_show(struct seq_file *s, void *v) "Disabled" : (f2fs_cp_error(si->sbi) ? "Error" : "Good")); if (si->sbi->s_flag) { seq_puts(s, "[SBI:"); - for_each_set_bit(j, &si->sbi->s_flag, 32) - seq_puts(s, s_flag[j]); + for_each_set_bit(j, &si->sbi->s_flag, MAX_SBI_FLAG) + seq_printf(s, " %s", s_flag[j]); seq_puts(s, "]\n"); } seq_printf(s, "[SB: 1] [CP: 2] [SIT: %d] [NAT: %d] ", diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 2b540d87859e..75db7c09bdfe 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -1271,7 +1271,10 @@ struct f2fs_gc_control { unsigned int nr_free_secs; /* # of free sections to do GC */ };
-/* For s_flag in struct f2fs_sb_info */ +/* + * For s_flag in struct f2fs_sb_info + * Modification on enum should be synchronized with s_flag array + */ enum { SBI_IS_DIRTY, /* dirty flag for checkpoint */ SBI_IS_CLOSE, /* specify unmounting */ @@ -1288,6 +1291,7 @@ enum { SBI_QUOTA_NEED_REPAIR, /* quota file may be corrupted */ SBI_IS_RESIZEFS, /* resizefs is in process */ SBI_IS_FREEZING, /* freezefs is in process */ + MAX_SBI_FLAG, };
enum {
linux-stable-mirror@lists.linaro.org