aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/super.c
diff options
context:
space:
mode:
authorslyich@gmail.com <slyich@gmail.com>2011-11-07 16:08:01 -0500
committerChris Mason <chris.mason@oracle.com>2011-11-07 16:08:01 -0500
commit45ea6095c8f0d6caad5658306416a5d254f1205e (patch)
tree84c25fabfb4b0a8e4fdbc16b5d29ba75ebf7a0ce /fs/btrfs/super.c
parent7c7e82a77fe3d89ae50824aa7c897454675eb4c4 (diff)
btrfs: fix double-free 'tree_root' in 'btrfs_mount()'
On error path 'tree_root' is treed in 'free_fs_info()'. No need to free it explicitely. Noticed by SLUB in debug mode: Complete reproducer under usermode linux (discovered on real machine): bdev=/dev/ubda btr_root=/btr /mkfs.btrfs $bdev mount $bdev $btr_root mkdir $btr_root/subvols/ cd $btr_root/subvols/ /btrfs su cr foo /btrfs su cr bar mount $bdev -osubvol=subvols/foo $btr_root/subvols/bar umount $btr_root/subvols/bar which gives device fsid 4d55aa28-45b1-474b-b4ec-da912322195e devid 1 transid 7 /dev/ubda ============================================================================= BUG kmalloc-2048: Object already free ----------------------------------------------------------------------------- INFO: Allocated in btrfs_mount+0x389/0x7f0 age=0 cpu=0 pid=277 INFO: Freed in btrfs_mount+0x51c/0x7f0 age=0 cpu=0 pid=277 INFO: Slab 0x0000000062886200 objects=15 used=9 fp=0x0000000070b4d2d0 flags=0x4081 INFO: Object 0x0000000070b4d2d0 @offset=21200 fp=0x0000000070b4a968 ... Call Trace: 70b31948: [<6008c522>] print_trailer+0xe2/0x130 70b31978: [<6008c5aa>] object_err+0x3a/0x50 70b319a8: [<6008e242>] free_debug_processing+0x142/0x2a0 70b319e0: [<600ebf6f>] btrfs_mount+0x55f/0x7f0 70b319f8: [<6008e5c1>] __slab_free+0x221/0x2d0 Signed-off-by: Sergei Trofimovich <slyfox@gentoo.org> Cc: Arne Jansen <sensille@gmx.net> Cc: Chris Mason <chris.mason@oracle.com> Cc: David Sterba <dsterba@suse.cz> Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/super.c')
-rw-r--r--fs/btrfs/super.c8
1 files changed, 5 insertions, 3 deletions
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
index 57080dffdfc6..dcd5aef6b614 100644
--- a/fs/btrfs/super.c
+++ b/fs/btrfs/super.c
@@ -933,8 +933,12 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags,
933 * then open_ctree will properly initialize everything later. 933 * then open_ctree will properly initialize everything later.
934 */ 934 */
935 fs_info = kzalloc(sizeof(struct btrfs_fs_info), GFP_NOFS); 935 fs_info = kzalloc(sizeof(struct btrfs_fs_info), GFP_NOFS);
936 if (!fs_info) {
937 error = -ENOMEM;
938 goto error_close_devices;
939 }
936 tree_root = kzalloc(sizeof(struct btrfs_root), GFP_NOFS); 940 tree_root = kzalloc(sizeof(struct btrfs_root), GFP_NOFS);
937 if (!fs_info || !tree_root) { 941 if (!tree_root) {
938 error = -ENOMEM; 942 error = -ENOMEM;
939 goto error_close_devices; 943 goto error_close_devices;
940 } 944 }
@@ -964,7 +968,6 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags,
964 968
965 btrfs_close_devices(fs_devices); 969 btrfs_close_devices(fs_devices);
966 free_fs_info(fs_info); 970 free_fs_info(fs_info);
967 kfree(tree_root);
968 } else { 971 } else {
969 char b[BDEVNAME_SIZE]; 972 char b[BDEVNAME_SIZE];
970 973
@@ -992,7 +995,6 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags,
992error_close_devices: 995error_close_devices:
993 btrfs_close_devices(fs_devices); 996 btrfs_close_devices(fs_devices);
994 free_fs_info(fs_info); 997 free_fs_info(fs_info);
995 kfree(tree_root);
996 return ERR_PTR(error); 998 return ERR_PTR(error);
997} 999}
998 1000