Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 381cf658 authored by David Sterba's avatar David Sterba
Browse files

btrfs: fix leak of path in btrfs_find_item



If btrfs_find_item is called with NULL path it allocates one locally but
does not free it. Affected paths are inserting an orphan item for a file
and for a subvol root.

Move the path allocation to the callers.

CC: <stable@vger.kernel.org> # 3.14+
Fixes: 3f870c28 ("btrfs: expand btrfs_find_item() to include find_orphan_item functionality")
Signed-off-by: default avatarDavid Sterba <dsterba@suse.cz>
parent eaa27f34
Loading
Loading
Loading
Loading
+4 −13
Original line number Original line Diff line number Diff line
@@ -2609,32 +2609,23 @@ static int key_search(struct extent_buffer *b, struct btrfs_key *key,
	return 0;
	return 0;
}
}


int btrfs_find_item(struct btrfs_root *fs_root, struct btrfs_path *found_path,
int btrfs_find_item(struct btrfs_root *fs_root, struct btrfs_path *path,
		u64 iobjectid, u64 ioff, u8 key_type,
		u64 iobjectid, u64 ioff, u8 key_type,
		struct btrfs_key *found_key)
		struct btrfs_key *found_key)
{
{
	int ret;
	int ret;
	struct btrfs_key key;
	struct btrfs_key key;
	struct extent_buffer *eb;
	struct extent_buffer *eb;
	struct btrfs_path *path;

	ASSERT(path);


	key.type = key_type;
	key.type = key_type;
	key.objectid = iobjectid;
	key.objectid = iobjectid;
	key.offset = ioff;
	key.offset = ioff;


	if (found_path == NULL) {
		path = btrfs_alloc_path();
		if (!path)
			return -ENOMEM;
	} else
		path = found_path;

	ret = btrfs_search_slot(NULL, fs_root, &key, path, 0, 0);
	ret = btrfs_search_slot(NULL, fs_root, &key, path, 0, 0);
	if ((ret < 0) || (found_key == NULL)) {
	if ((ret < 0) || (found_key == NULL))
		if (path != found_path)
			btrfs_free_path(path);
		return ret;
		return ret;
	}


	eb = path->nodes[0];
	eb = path->nodes[0];
	if (ret && path->slots[0] >= btrfs_header_nritems(eb)) {
	if (ret && path->slots[0] >= btrfs_header_nritems(eb)) {
+8 −1
Original line number Original line Diff line number Diff line
@@ -1630,6 +1630,7 @@ struct btrfs_root *btrfs_get_fs_root(struct btrfs_fs_info *fs_info,
				     bool check_ref)
				     bool check_ref)
{
{
	struct btrfs_root *root;
	struct btrfs_root *root;
	struct btrfs_path *path;
	int ret;
	int ret;


	if (location->objectid == BTRFS_ROOT_TREE_OBJECTID)
	if (location->objectid == BTRFS_ROOT_TREE_OBJECTID)
@@ -1669,8 +1670,14 @@ struct btrfs_root *btrfs_get_fs_root(struct btrfs_fs_info *fs_info,
	if (ret)
	if (ret)
		goto fail;
		goto fail;


	ret = btrfs_find_item(fs_info->tree_root, NULL, BTRFS_ORPHAN_OBJECTID,
	path = btrfs_alloc_path();
	if (!path) {
		ret = -ENOMEM;
		goto fail;
	}
	ret = btrfs_find_item(fs_info->tree_root, path, BTRFS_ORPHAN_OBJECTID,
			location->objectid, BTRFS_ORPHAN_ITEM_KEY, NULL);
			location->objectid, BTRFS_ORPHAN_ITEM_KEY, NULL);
	btrfs_free_path(path);
	if (ret < 0)
	if (ret < 0)
		goto fail;
		goto fail;
	if (ret == 0)
	if (ret == 0)
+10 −1
Original line number Original line Diff line number Diff line
@@ -1257,10 +1257,19 @@ static int insert_orphan_item(struct btrfs_trans_handle *trans,
			      struct btrfs_root *root, u64 offset)
			      struct btrfs_root *root, u64 offset)
{
{
	int ret;
	int ret;
	ret = btrfs_find_item(root, NULL, BTRFS_ORPHAN_OBJECTID,
	struct btrfs_path *path;

	path = btrfs_alloc_path();
	if (!path)
		return -ENOMEM;

	ret = btrfs_find_item(root, path, BTRFS_ORPHAN_OBJECTID,
			offset, BTRFS_ORPHAN_ITEM_KEY, NULL);
			offset, BTRFS_ORPHAN_ITEM_KEY, NULL);
	if (ret > 0)
	if (ret > 0)
		ret = btrfs_insert_orphan_item(trans, root, offset);
		ret = btrfs_insert_orphan_item(trans, root, offset);

	btrfs_free_path(path);

	return ret;
	return ret;
}
}