lkml.org 
[lkml]   [2024]   [May]   [9]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
From
SubjectRe: [PATCH v3 03/26] ext4: correct the hole length returned by ext4_map_blocks()
Date
On Sat 27 Jan 2024 09:58:02 AM +08, Zhang Yi wrote;
<...>
> +static ext4_lblk_t ext4_ext_determine_insert_hole(struct inode *inode,
> + struct ext4_ext_path *path,
> + ext4_lblk_t lblk)
> +{
> + ext4_lblk_t hole_start, len;
> + struct extent_status es;
> +
> + hole_start = lblk;
> + len = ext4_ext_find_hole(inode, path, &hole_start);
> +again:
> + ext4_es_find_extent_range(inode, &ext4_es_is_delayed, hole_start,
> + hole_start + len - 1, &es);
> + if (!es.es_len)
> + goto insert_hole;
> +
> + /*
> + * There's a delalloc extent in the hole, handle it if the delalloc
> + * extent is in front of, behind and straddle the queried range.
> + */
> + if (lblk >= es.es_lblk + es.es_len) {
> + /*
> + * The delalloc extent is in front of the queried range,
> + * find again from the queried start block.
> + */
> + len -= lblk - hole_start;
> + hole_start = lblk;
> + goto again;

It's looks like it's easy to trigger an infinite loop here using fstest
generic/039. If I understand it correctly (which doesn't happen as often
as I'd like), this is due to an integer overflow in the 'if' condition,
and should be fixed with the patch below.

From 3117af2f8dacad37a2722850421f31075ae9e88d Mon Sep 17 00:00:00 2001
From: "Luis Henriques (SUSE)" <luis.henriques@linux.dev>
Date: Thu, 9 May 2024 15:53:01 +0100
Subject: [PATCH] ext4: fix infinite loop caused by integer overflow

An integer overflow will happen if the extent_status len is set to
EXT_MAX_BLOCKS (0xffffffff). This may cause an infinite loop in function
ext4_ext_determine_insert_hole(), easily reproducible using fstest
generic/039.

Fixes: 6430dea07e85 ("ext4: correct the hole length returned by ext4_map_blocks()")
Signed-off-by: Luis Henriques (SUSE) <luis.henriques@linux.dev>
---
fs/ext4/extents.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index e57054bdc5fd..193121b394f9 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -4064,7 +4064,7 @@ static ext4_lblk_t ext4_ext_determine_insert_hole(struct inode *inode,
* There's a delalloc extent in the hole, handle it if the delalloc
* extent is in front of, behind and straddle the queried range.
*/
- if (lblk >= es.es_lblk + es.es_len) {
+ if (lblk >= ((__u64) es.es_lblk) + es.es_len) {
/*
* The delalloc extent is in front of the queried range,
* find again from the queried start block.
\
 
 \ /
  Last update: 2024-05-09 17:16    [W:0.444 / U:0.096 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site