Skip to content

Commit

Permalink
Btrfs: avoid null dereference and leaks when bailing from open_ctree()
Browse files Browse the repository at this point in the history
Fix bugs introduced by 6c41761.  Firstly, after failing to allocate any
of the tree roots (first 'goto fail' in open_ctree()) we would
dereference a NULL fs_info pointer in free_fs_info().  Secondly, after
failures from init_srcu_struct(), setup_bdi() and new_inode() we would
leak all earlier allocated roots: fs_info fields haven't been
initialized yet so free_fs_info() is rendered useless.

Fix this by initializing fs_info pointer and fs_info fields before any
allocations happen.

Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
  • Loading branch information
Ilya Dryomov committed Nov 9, 2011
1 parent f23c8af commit 4d34b27
Showing 1 changed file with 15 additions and 20 deletions.
35 changes: 15 additions & 20 deletions fs/btrfs/disk-io.c
Original file line number Diff line number Diff line change
Expand Up @@ -1890,31 +1890,32 @@ struct btrfs_root *open_ctree(struct super_block *sb,
u64 features;
struct btrfs_key location;
struct buffer_head *bh;
struct btrfs_root *extent_root = kzalloc(sizeof(struct btrfs_root),
GFP_NOFS);
struct btrfs_root *csum_root = kzalloc(sizeof(struct btrfs_root),
GFP_NOFS);
struct btrfs_super_block *disk_super;
struct btrfs_root *tree_root = btrfs_sb(sb);
struct btrfs_fs_info *fs_info = NULL;
struct btrfs_root *chunk_root = kzalloc(sizeof(struct btrfs_root),
GFP_NOFS);
struct btrfs_root *dev_root = kzalloc(sizeof(struct btrfs_root),
GFP_NOFS);
struct btrfs_fs_info *fs_info = tree_root->fs_info;
struct btrfs_root *extent_root;
struct btrfs_root *csum_root;
struct btrfs_root *chunk_root;
struct btrfs_root *dev_root;
struct btrfs_root *log_tree_root;

int ret;
int err = -EINVAL;
int num_backups_tried = 0;
int backup_index = 0;

struct btrfs_super_block *disk_super;
extent_root = fs_info->extent_root =
kzalloc(sizeof(struct btrfs_root), GFP_NOFS);
csum_root = fs_info->csum_root =
kzalloc(sizeof(struct btrfs_root), GFP_NOFS);
chunk_root = fs_info->chunk_root =
kzalloc(sizeof(struct btrfs_root), GFP_NOFS);
dev_root = fs_info->dev_root =
kzalloc(sizeof(struct btrfs_root), GFP_NOFS);

if (!extent_root || !tree_root || !tree_root->fs_info ||
!chunk_root || !dev_root || !csum_root) {
if (!extent_root || !csum_root || !chunk_root || !dev_root) {
err = -ENOMEM;
goto fail;
}
fs_info = tree_root->fs_info;

ret = init_srcu_struct(&fs_info->subvol_srcu);
if (ret) {
Expand Down Expand Up @@ -1954,12 +1955,6 @@ struct btrfs_root *open_ctree(struct super_block *sb,
mutex_init(&fs_info->reloc_mutex);

init_completion(&fs_info->kobj_unregister);
fs_info->tree_root = tree_root;
fs_info->extent_root = extent_root;
fs_info->csum_root = csum_root;
fs_info->chunk_root = chunk_root;
fs_info->dev_root = dev_root;
fs_info->fs_devices = fs_devices;
INIT_LIST_HEAD(&fs_info->dirty_cowonly_roots);
INIT_LIST_HEAD(&fs_info->space_info);
btrfs_mapping_init(&fs_info->mapping_tree);
Expand Down

0 comments on commit 4d34b27

Please sign in to comment.