f2fs: fix several potential integer overflows in file offsets

When dealing with large extents and calculating file offsets by
summing up according extent offsets and lengths of unsigned int type,
one may encounter possible integer overflow if the values are
big enough.

Prevent this from happening by expanding one of the addends to
(pgoff_t) type.

Found by Linux Verification Center (linuxtesting.org) with static
analysis tool SVACE.

Fixes: d323d005ac ("f2fs: support file defragment")
Cc: stable@vger.kernel.org
Signed-off-by: Nikita Zhandarovich <n.zhandarovich@fintech.ru>
Reviewed-by: Chao Yu <chao@kernel.org>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
This commit is contained in:
Nikita Zhandarovich 2024-07-24 10:28:38 -07:00 committed by Jaegeuk Kim
parent 47f268f33d
commit 1cade98cf6
2 changed files with 3 additions and 3 deletions

View File

@ -366,7 +366,7 @@ static unsigned int __free_extent_tree(struct f2fs_sb_info *sbi,
static void __drop_largest_extent(struct extent_tree *et, static void __drop_largest_extent(struct extent_tree *et,
pgoff_t fofs, unsigned int len) pgoff_t fofs, unsigned int len)
{ {
if (fofs < et->largest.fofs + et->largest.len && if (fofs < (pgoff_t)et->largest.fofs + et->largest.len &&
fofs + len > et->largest.fofs) { fofs + len > et->largest.fofs) {
et->largest.len = 0; et->largest.len = 0;
et->largest_updated = true; et->largest_updated = true;
@ -456,7 +456,7 @@ static bool __lookup_extent_tree(struct inode *inode, pgoff_t pgofs,
if (type == EX_READ && if (type == EX_READ &&
et->largest.fofs <= pgofs && et->largest.fofs <= pgofs &&
et->largest.fofs + et->largest.len > pgofs) { (pgoff_t)et->largest.fofs + et->largest.len > pgofs) {
*ei = et->largest; *ei = et->largest;
ret = true; ret = true;
stat_inc_largest_node_hit(sbi); stat_inc_largest_node_hit(sbi);

View File

@ -2710,7 +2710,7 @@ static int f2fs_defragment_range(struct f2fs_sb_info *sbi,
* block addresses are continuous. * block addresses are continuous.
*/ */
if (f2fs_lookup_read_extent_cache(inode, pg_start, &ei)) { if (f2fs_lookup_read_extent_cache(inode, pg_start, &ei)) {
if (ei.fofs + ei.len >= pg_end) if ((pgoff_t)ei.fofs + ei.len >= pg_end)
goto out; goto out;
} }