Btrfs: fix use after free when close_ctree frees the orphan_rsv
authorChris Mason <clm@fb.com>
Tue, 7 Apr 2015 01:17:00 +0000 (18:17 -0700)
committerChris Mason <clm@fb.com>
Fri, 10 Apr 2015 21:07:29 +0000 (14:07 -0700)
Near the end of close_ctree, we're calling btrfs_free_block_rsv
to free up the orphan rsv.  The problem is this call updates the
space_info, which has already been freed.

This adds a new __ function that directly calls kfree instead of trying
to update the space infos.

Signed-off-by: Chris Mason <clm@fb.com>
fs/btrfs/ctree.h
fs/btrfs/disk-io.c
fs/btrfs/extent-tree.c

index 83051fae946741037070e8b4620bb68663f31547..10b6a75ab7e62c4ffc675fb53e8de1b069c458d7 100644 (file)
@@ -3470,6 +3470,7 @@ struct btrfs_block_rsv *btrfs_alloc_block_rsv(struct btrfs_root *root,
                                              unsigned short type);
 void btrfs_free_block_rsv(struct btrfs_root *root,
                          struct btrfs_block_rsv *rsv);
+void __btrfs_free_block_rsv(struct btrfs_block_rsv *rsv);
 int btrfs_block_rsv_add(struct btrfs_root *root,
                        struct btrfs_block_rsv *block_rsv, u64 num_bytes,
                        enum btrfs_reserve_flush_enum flush);
index b5e3d5f6400af923137d43424b1cd27dcc81af99..62cd3b63190d97d68b11f9bc11ddb9577b24337b 100644 (file)
@@ -3766,7 +3766,7 @@ void close_ctree(struct btrfs_root *root)
 
        btrfs_free_stripe_hash_table(fs_info);
 
-       btrfs_free_block_rsv(root, root->orphan_block_rsv);
+       __btrfs_free_block_rsv(root->orphan_block_rsv);
        root->orphan_block_rsv = NULL;
 
        lock_chunks(root);
index 02c2b29a084017b53e2052f4bede1355590028ec..875ba519a131bd3d45ea8c9ceb8fbbda07183dc7 100644 (file)
@@ -4918,6 +4918,11 @@ void btrfs_free_block_rsv(struct btrfs_root *root,
        kfree(rsv);
 }
 
+void __btrfs_free_block_rsv(struct btrfs_block_rsv *rsv)
+{
+       kfree(rsv);
+}
+
 int btrfs_block_rsv_add(struct btrfs_root *root,
                        struct btrfs_block_rsv *block_rsv, u64 num_bytes,
                        enum btrfs_reserve_flush_enum flush)