7.3-stable review patch. If anyone has any objections, please let me know. ------------------ From: Darrick J. Wong commit 00f32fdf54983371d39162efef7df693e2842ffb upstream. LOLLM pointed out some underspecified parts of the xbitmap{32,64} API. Specifically, the behavior of set/clear/test functions when the length parameter is zero is not well defined, nor is what happens when someone tries to disunion a bitmap with itself. None of these situations are expected, but we'll define zero-length set and clear to be nops, and the rest to be checked by assertions. Cc: stable@vger.kernel.org # v6.8 Fixes: 6ece924b952262 ("xfs: create separate structures and code for u32 bitmaps") Signed-off-by: Darrick J. Wong Assisted-by: LOLLM # finding obvious bugs Reviewed-by: Christoph Hellwig Signed-off-by: Carlos Maiolino Signed-off-by: Greg Kroah-Hartman --- fs/xfs/scrub/bitmap.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) --- a/fs/xfs/scrub/bitmap.c +++ b/fs/xfs/scrub/bitmap.c @@ -77,6 +77,9 @@ xbitmap64_clear( struct xbitmap64_node *new_bn; uint64_t last = start + len - 1; + if (!len) + return 0; + while ((bn = xbitmap64_tree_iter_first(&bitmap->xb_root, start, last))) { if (bn->bn_start < start && bn->bn_last > last) { uint64_t old_last = bn->bn_last; @@ -127,6 +130,9 @@ xbitmap64_set( uint64_t last = start + len - 1; int error; + if (!len) + return 0; + /* Is this whole range already set? */ left = xbitmap64_tree_iter_first(&bitmap->xb_root, start, last); if (left && left->bn_start <= start && left->bn_last >= last) @@ -223,6 +229,8 @@ xbitmap64_disunion( struct xbitmap64_node *bn; int error; + ASSERT(bitmap != sub); + if (xbitmap64_empty(bitmap) || xbitmap64_empty(sub)) return 0; @@ -287,6 +295,8 @@ xbitmap64_test( struct xbitmap64_node *bn; uint64_t last = start + *len - 1; + ASSERT(*len > 0); + bn = xbitmap64_tree_iter_first(&bitmap->xb_root, start, last); if (!bn) return false; @@ -357,6 +367,9 @@ xbitmap32_clear( struct xbitmap32_node *new_bn; uint32_t last = start + len - 1; + if (!len) + return 0; + while ((bn = xbitmap32_tree_iter_first(&bitmap->xb_root, start, last))) { if (bn->bn_start < start && bn->bn_last > last) { uint32_t old_last = bn->bn_last; @@ -407,6 +420,9 @@ xbitmap32_set( uint32_t last = start + len - 1; int error; + if (!len) + return 0; + /* Is this whole range already set? */ left = xbitmap32_tree_iter_first(&bitmap->xb_root, start, last); if (left && left->bn_start <= start && left->bn_last >= last) @@ -503,6 +519,8 @@ xbitmap32_disunion( struct xbitmap32_node *bn; int error; + ASSERT(bitmap != sub); + if (xbitmap32_empty(bitmap) || xbitmap32_empty(sub)) return 0; @@ -567,6 +585,8 @@ xbitmap32_test( struct xbitmap32_node *bn; uint32_t last = start + *len - 1; + ASSERT(*len > 0); + bn = xbitmap32_tree_iter_first(&bitmap->xb_root, start, last); if (!bn) return false;