aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs
diff options
context:
space:
mode:
authorNikolay Borisov <kernel@kyup.com>2016-06-29 02:46:41 -0400
committerDavid Sterba <dsterba@suse.com>2016-07-26 07:52:25 -0400
commit3d48d9810de4ee1bca4a1c905efd0618944904cd (patch)
tree1bdd8f5dd630aa97d03bd17cda4049d84335eebc /fs/btrfs
parentfb770ae414d018255afa7a70b14ba1f8620762dd (diff)
btrfs: Handle uninitialised inode eviction
The code flow in btrfs_new_inode allows for btrfs_evict_inode to be called with not fully initialised inode (e.g. ->root member not being set). This can happen when btrfs_set_inode_index in btrfs_new_inode fails, which in turn would call iput for the newly allocated inode. This in turn leads to vfs calling into btrfs_evict_inode. This leads to null pointer dereference. To handle this situation check whether the passed inode has root set and just free it in case it doesn't. Signed-off-by: Nikolay Borisov <kernel@kyup.com> Reviewed-by: Josef Bacik <jbacik@fb.com> Signed-off-by: David Sterba <dsterba@suse.com>
Diffstat (limited to 'fs/btrfs')
-rw-r--r--fs/btrfs/inode.c9
1 files changed, 8 insertions, 1 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 3e61bd1f3f65..5c2c076bc552 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -5159,11 +5159,18 @@ void btrfs_evict_inode(struct inode *inode)
5159 struct btrfs_root *root = BTRFS_I(inode)->root; 5159 struct btrfs_root *root = BTRFS_I(inode)->root;
5160 struct btrfs_block_rsv *rsv, *global_rsv; 5160 struct btrfs_block_rsv *rsv, *global_rsv;
5161 int steal_from_global = 0; 5161 int steal_from_global = 0;
5162 u64 min_size = btrfs_calc_trunc_metadata_size(root, 1); 5162 u64 min_size;
5163 int ret; 5163 int ret;
5164 5164
5165 trace_btrfs_inode_evict(inode); 5165 trace_btrfs_inode_evict(inode);
5166 5166
5167 if (!root) {
5168 kmem_cache_free(btrfs_inode_cachep, BTRFS_I(inode));
5169 return;
5170 }
5171
5172 min_size = btrfs_calc_trunc_metadata_size(root, 1);
5173
5167 evict_inode_truncate_pages(inode); 5174 evict_inode_truncate_pages(inode);
5168 5175
5169 if (inode->i_nlink && 5176 if (inode->i_nlink &&