From: Yao Xiao To: Jaegeuk Kim , Chao Yu Cc: linux-f2fs-devel@lists.sourceforge.net, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v2] f2fs: add overflow/underflow checks to update_sit_entry The update_sit_entry() function performs an arithmetic operation between se->valid_blocks (a 10-bit unsigned bitfield) and a signed integer 'del'. Under C integer promotion rules, the signed integer is converted to unsigned before the addition, which can lead to wraparound behavior: - If 'del' is negative and large, it becomes a large unsigned integer, resulting in an unintended huge positive addition. - If 'del' is positive and large, the result can exceed the bitfield's maximum representable range. To avoid undefined behavior caused by performing the arithmetic first and validating the result afterwards, this patch adds explicit overflow/underflow checks before computing the new value. This ensures the operation is safe and prevents inconsistent SIT metadata updates. This change follows the defensive overflow check style used in previous f2fs fixes addressing similar boundary issues. Signed-off-by: Yao Xiao --- fs/f2fs/segment.c | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c index b45eace879d7..05ab34600e32 100644 --- a/fs/f2fs/segment.c +++ b/fs/f2fs/segment.c @@ -2569,13 +2569,33 @@ static void update_sit_entry(struct f2fs_sb_info *sbi, block_t blkaddr, int del) struct seg_entry *se; unsigned int segno, offset; long int new_vblocks; + unsigned int max_valid; segno = GET_SEGNO(sbi, blkaddr); if (segno == NULL_SEGNO) return; se = get_seg_entry(sbi, segno); - new_vblocks = se->valid_blocks + del; + max_valid = f2fs_usable_blks_in_seg(sbi, segno); + + /* Prevent overflow/underflow before performing arithmetic. */ + if (del > 0) { + if ((unsigned int)del > max_valid || + se->valid_blocks > max_valid - (unsigned int)del) { + f2fs_bug_on(sbi, 1); + return; + } + } else if (del < 0) { + if (se->valid_blocks < (unsigned int)(-del)) { + f2fs_bug_on(sbi, 1); + return; + } + } + + new_vblocks = (long int)se->valid_blocks + del; offset = GET_BLKOFF_FROM_SEG0(sbi, blkaddr); f2fs_bug_on(sbi, (new_vblocks < 0 || -- 2.34.1