From: Theodore Ts'o Date: Fri, 6 Jun 2025 13:07:11 +0000 (-0400) Subject: libext2fs: fix a extent tree corruption bug in ext2fs_extent_set_bmap() X-Git-Tag: v1.47.3-rc2~20 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=b914701223255c116745a11f30563652c9fdbb4b;p=thirdparty%2Fe2fsprogs.git libext2fs: fix a extent tree corruption bug in ext2fs_extent_set_bmap() In the case where we are moving a particular logical block mapping from a particular extent tree entry, to the immediately precending entry (when the physical block or uninitialized flag is changing so it can be coalesced with the precending entry) and the precending entry is in a different extent tree block, the resulting extent tree can get corrupted. Fix this by removing the original logical block mapping before adding the new logical block mapping. Per the warning in the comments before ext2fs_extents_fix_parents(): Note a subtlety of this function -- if there happen to be two extents mapping the same lblk and someone calls fix_parents on the second of the two extents, the position of the extent handle after the call will be the second extent if nothing happened, or the first extent if something did. A caller in this situation must use ext2fs_extent_goto() after calling this function. Or simply don't map the same lblk with two extents, ever. Signed-off-by: Theodore Ts'o --- diff --git a/lib/ext2fs/extent.c b/lib/ext2fs/extent.c index 013ea2f6..b33c6f91 100644 --- a/lib/ext2fs/extent.c +++ b/lib/ext2fs/extent.c @@ -1531,6 +1531,15 @@ errcode_t ext2fs_extent_set_bmap(ext2_extent_handle_t handle, #ifdef DEBUG printf("(re/un)mapping first block in extent\n"); #endif + extent.e_pblk++; + extent.e_lblk++; + extent.e_len--; + retval = ext2fs_extent_replace(handle, 0, &extent); + if (retval) + goto done; + retval = ext2fs_extent_fix_parents(handle); + if (retval) + goto done; if (physical) { if (has_prev && (logical == (prev_extent.e_lblk + @@ -1560,15 +1569,6 @@ errcode_t ext2fs_extent_set_bmap(ext2_extent_handle_t handle, if (retval) goto done; } - extent.e_pblk++; - extent.e_lblk++; - extent.e_len--; - retval = ext2fs_extent_replace(handle, 0, &extent); - if (retval) - goto done; - retval = ext2fs_extent_fix_parents(handle); - if (retval) - goto done; } else { __u32 save_length; blk64_t save_lblk;