Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1357272f authored by Ilya Dryomov's avatar Ilya Dryomov Committed by Josef Bacik
Browse files

Btrfs: fix a use-after-free bug in btrfs_dev_replace_finishing



free_device rcu callback, scheduled from btrfs_rm_dev_replace_srcdev,
can be processed before btrfs_scratch_superblock is called, which would
result in a use-after-free on btrfs_device contents.  Fix this by
zeroing the superblock before the rcu callback is registered.

Cc: Stefan Behrens <sbehrens@giantdisaster.de>
Signed-off-by: default avatarIlya Dryomov <idryomov@gmail.com>
Signed-off-by: default avatarJosef Bacik <jbacik@fusionio.com>
parent 964fb15a
Loading
Loading
Loading
Loading
+1 −4
Original line number Diff line number Diff line
@@ -535,10 +535,7 @@ static int btrfs_dev_replace_finishing(struct btrfs_fs_info *fs_info,
	list_add(&tgt_device->dev_alloc_list, &fs_info->fs_devices->alloc_list);

	btrfs_rm_dev_replace_srcdev(fs_info, src_device);
	if (src_device->bdev) {
		/* zero out the old super */
		btrfs_scratch_superblock(src_device);
	}

	/*
	 * this is again a consistent state where no dev_replace procedure
	 * is running, the target device is part of the filesystem, the
+6 −1
Original line number Diff line number Diff line
@@ -1716,6 +1716,7 @@ void btrfs_rm_dev_replace_srcdev(struct btrfs_fs_info *fs_info,
				 struct btrfs_device *srcdev)
{
	WARN_ON(!mutex_is_locked(&fs_info->fs_devices->device_list_mutex));

	list_del_rcu(&srcdev->dev_list);
	list_del_rcu(&srcdev->dev_alloc_list);
	fs_info->fs_devices->num_devices--;
@@ -1725,9 +1726,13 @@ void btrfs_rm_dev_replace_srcdev(struct btrfs_fs_info *fs_info,
	}
	if (srcdev->can_discard)
		fs_info->fs_devices->num_can_discard--;
	if (srcdev->bdev)
	if (srcdev->bdev) {
		fs_info->fs_devices->open_devices--;

		/* zero out the old super */
		btrfs_scratch_superblock(srcdev);
	}

	call_rcu(&srcdev->rcu, free_device);
}