Commit 1357272fc7deeebb7b3c5d1a071562edc273cdaf

Authored by Ilya Dryomov
Committed by Josef Bacik
1 parent 964fb15acf

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: Ilya Dryomov <idryomov@gmail.com>
Signed-off-by: Josef Bacik <jbacik@fusionio.com>

Showing 2 changed files with 7 additions and 5 deletions Side-by-side Diff

fs/btrfs/dev-replace.c
... ... @@ -535,10 +535,7 @@
535 535 list_add(&tgt_device->dev_alloc_list, &fs_info->fs_devices->alloc_list);
536 536  
537 537 btrfs_rm_dev_replace_srcdev(fs_info, src_device);
538   - if (src_device->bdev) {
539   - /* zero out the old super */
540   - btrfs_scratch_superblock(src_device);
541   - }
  538 +
542 539 /*
543 540 * this is again a consistent state where no dev_replace procedure
544 541 * is running, the target device is part of the filesystem, the
... ... @@ -1716,6 +1716,7 @@
1716 1716 struct btrfs_device *srcdev)
1717 1717 {
1718 1718 WARN_ON(!mutex_is_locked(&fs_info->fs_devices->device_list_mutex));
  1719 +
1719 1720 list_del_rcu(&srcdev->dev_list);
1720 1721 list_del_rcu(&srcdev->dev_alloc_list);
1721 1722 fs_info->fs_devices->num_devices--;
1722 1723  
... ... @@ -1725,8 +1726,12 @@
1725 1726 }
1726 1727 if (srcdev->can_discard)
1727 1728 fs_info->fs_devices->num_can_discard--;
1728   - if (srcdev->bdev)
  1729 + if (srcdev->bdev) {
1729 1730 fs_info->fs_devices->open_devices--;
  1731 +
  1732 + /* zero out the old super */
  1733 + btrfs_scratch_superblock(srcdev);
  1734 + }
1730 1735  
1731 1736 call_rcu(&srcdev->rcu, free_device);
1732 1737 }