btrfs: fix leak of path in btrfs_find_item
authorDavid Sterba <dsterba@suse.cz>
Fri, 2 Jan 2015 17:45:16 +0000 (18:45 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 6 Mar 2015 22:43:32 +0000 (14:43 -0800)
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: 3f870c289900 ("btrfs: expand btrfs_find_item() to include find_orphan_item functionality")
Signed-off-by: David Sterba <dsterba@suse.cz>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
fs/btrfs/ctree.c
fs/btrfs/disk-io.c
fs/btrfs/tree-log.c

index cbd3a7d6fa681acfc0b00cb515fcddbcf8880f49..93de3ba994e7ea40b95e6f7881cc74bf6a3670fc 100644 (file)
@@ -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)) {
index 7a5278dd132ea6eb7f9250e94ea0013a139db488..f48d5fc352a919dd45d4ef2ac78287e000d2d1bf 100644 (file)
@@ -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)
@@ -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)
index 39d83da03e0398db90428e52b98524982da469b5..aeb57b98c53f33050a5a4bd1a9311885c3349685 100644 (file)
@@ -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;
 }