Skip to content

Commit

Permalink
btrfs: fix leak of path in btrfs_find_item
Browse files Browse the repository at this point in the history
commit 381cf6587f8a8a8e981bc0c1aaaa8859b51dc756 upstream.

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.

Fixes: 3f870c2 ("btrfs: expand btrfs_find_item() to include find_orphan_item functionality")
Signed-off-by: David Sterba <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
  • Loading branch information
kdave authored and gregkh committed Mar 6, 2015
1 parent 74e4236 commit f9e2ba6
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 15 deletions.
17 changes: 4 additions & 13 deletions fs/btrfs/ctree.c
Original file line number Diff line number Diff line change
Expand Up @@ -2655,32 +2655,23 @@ static int key_search(struct extent_buffer *b, struct btrfs_key *key,
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,
struct btrfs_key *found_key)
{
int ret;
struct btrfs_key key;
struct extent_buffer *eb;
struct btrfs_path *path;

ASSERT(path);

key.type = key_type;
key.objectid = iobjectid;
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);
if ((ret < 0) || (found_key == NULL)) {
if (path != found_path)
btrfs_free_path(path);
if ((ret < 0) || (found_key == NULL))
return ret;
}

eb = path->nodes[0];
if (ret && path->slots[0] >= btrfs_header_nritems(eb)) {
Expand Down
9 changes: 8 additions & 1 deletion fs/btrfs/disk-io.c
Original file line number Diff line number Diff line change
Expand Up @@ -1560,6 +1560,7 @@ struct btrfs_root *btrfs_get_fs_root(struct btrfs_fs_info *fs_info,
bool check_ref)
{
struct btrfs_root *root;
struct btrfs_path *path;
int ret;

if (location->objectid == BTRFS_ROOT_TREE_OBJECTID)
Expand Down Expand Up @@ -1599,8 +1600,14 @@ struct btrfs_root *btrfs_get_fs_root(struct btrfs_fs_info *fs_info,
if (ret)
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);
btrfs_free_path(path);
if (ret < 0)
goto fail;
if (ret == 0)
Expand Down
11 changes: 10 additions & 1 deletion fs/btrfs/tree-log.c
Original file line number Diff line number Diff line change
Expand Up @@ -1238,10 +1238,19 @@ static int insert_orphan_item(struct btrfs_trans_handle *trans,
struct btrfs_root *root, u64 offset)
{
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);
if (ret > 0)
ret = btrfs_insert_orphan_item(trans, root, offset);

btrfs_free_path(path);

return ret;
}

Expand Down

0 comments on commit f9e2ba6

Please sign in to comment.