[PATCH] btrfs: Fix root reference leak in handle_indirect_tree_backref()

Wentao Liang posted 1 patch 1 week, 1 day ago
fs/btrfs/backref.c | 6 ++++++
1 file changed, 6 insertions(+)
[PATCH] btrfs: Fix root reference leak in handle_indirect_tree_backref()
Posted by Wentao Liang 1 week, 1 day ago
handle_indirect_tree_backref() walks up the tree from @cur, storing the
reference returned by btrfs_get_fs_root() in lower->root when the top
of the searched path is reached, and dropping it once a node already in
the backref cache is found.  If the walk instead reaches
BTRFS_MAX_LEVEL without hitting either of those two exits, the
reference is neither stored nor dropped and is leaked on return.

Drop the reference and return -EUCLEAN if the walk reaches
BTRFS_MAX_LEVEL without finding the root of the tree.

Fixes: 1b60d2ec982a ("btrfs: backref: rename and move handle_one_tree_block()")
Cc: stable@vger.kernel.org
Signed-off-by: Wentao Liang <vulab@iscas.ac.cn>
---
 fs/btrfs/backref.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/fs/btrfs/backref.c b/fs/btrfs/backref.c
index 273924ca912c..e889fbec4fe1 100644
--- a/fs/btrfs/backref.c
+++ b/fs/btrfs/backref.c
@@ -3426,6 +3426,12 @@ static int handle_indirect_tree_backref(struct btrfs_trans_handle *trans,
 		lower = upper;
 		upper = NULL;
 	}
+	/* We walked up to BTRFS_MAX_LEVEL without reaching the tree root. */
+	if (level == BTRFS_MAX_LEVEL) {
+		btrfs_put_root(root);
+		ret = -EUCLEAN;
+		goto out;
+	}
 out:
 	btrfs_release_path(path);
 	return ret;
-- 
2.34.1
Re: [PATCH] btrfs: Fix root reference leak in handle_indirect_tree_backref()
Posted by Boris Burkov 6 days, 8 hours ago
On Wed, Sep 16, 2026 at 05:13:19PM +0000, Wentao Liang wrote:
> handle_indirect_tree_backref() walks up the tree from @cur, storing the
> reference returned by btrfs_get_fs_root() in lower->root when the top
> of the searched path is reached, and dropping it once a node already in
> the backref cache is found.  If the walk instead reaches
> BTRFS_MAX_LEVEL without hitting either of those two exits, the
> reference is neither stored nor dropped and is leaked on return.

Are you able to reproduce this bug? If so, can you include that
information in the commit message.

> 
> Drop the reference and return -EUCLEAN if the walk reaches
> BTRFS_MAX_LEVEL without finding the root of the tree.
> 
> Fixes: 1b60d2ec982a ("btrfs: backref: rename and move handle_one_tree_block()")
> Cc: stable@vger.kernel.org
> Signed-off-by: Wentao Liang <vulab@iscas.ac.cn>
> ---
>  fs/btrfs/backref.c | 6 ++++++
>  1 file changed, 6 insertions(+)
> 
> diff --git a/fs/btrfs/backref.c b/fs/btrfs/backref.c
> index 273924ca912c..e889fbec4fe1 100644
> --- a/fs/btrfs/backref.c
> +++ b/fs/btrfs/backref.c
> @@ -3426,6 +3426,12 @@ static int handle_indirect_tree_backref(struct btrfs_trans_handle *trans,
>  		lower = upper;
>  		upper = NULL;
>  	}
> +	/* We walked up to BTRFS_MAX_LEVEL without reaching the tree root. */
> +	if (level == BTRFS_MAX_LEVEL) {
> +		btrfs_put_root(root);
> +		ret = -EUCLEAN;
> +		goto out;
> +	}
>  out:
>  	btrfs_release_path(path);
>  	return ret;
> -- 
> 2.34.1
>
Re: [PATCH] btrfs: Fix root reference leak in handle_indirect_tree_backref()
Posted by David Sterba 3 days, 15 hours ago
On Fri, Sep 18, 2026 at 12:13:42PM -0700, Boris Burkov wrote:
> On Wed, Sep 16, 2026 at 05:13:19PM +0000, Wentao Liang wrote:
> > handle_indirect_tree_backref() walks up the tree from @cur, storing the
> > reference returned by btrfs_get_fs_root() in lower->root when the top
> > of the searched path is reached, and dropping it once a node already in
> > the backref cache is found.  If the walk instead reaches
> > BTRFS_MAX_LEVEL without hitting either of those two exits, the
> > reference is neither stored nor dropped and is leaked on return.
> 
> Are you able to reproduce this bug? If so, can you include that
> information in the commit message.

A filesystem with a tree of maximum height consumes a lot of metadata
space and in practice it's difficult to create one. For completeness the
check could be there, we have other impossible condition checks
elsewhere too.