Commit f9c365eb authored by Zhihao Cheng's avatar Zhihao Cheng Committed by Long Li
Browse files

btrfs: fix use-after-free of block device file in __btrfs_free_extra_devids()

mainline inclusion
from mainline-v6.10-rc2
commit aec8e6bf839101784f3ef037dcdb9432c3f32343
category: bugfix
bugzilla: https://gitee.com/src-openeuler/kernel/issues/IB37A4
CVE: CVE-2024-50217

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=aec8e6bf839101784f3ef037dcdb9432c3f32343

--------------------------------

Mounting btrfs from two images (which have the same one fsid and two
different dev_uuids) in certain executing order may trigger an UAF for
variable 'device->bdev_file' in __btrfs_free_extra_devids(). And
following are the details:

1. Attach image_1 to loop0, attach image_2 to loop1, and scan btrfs
   devices by ioctl(BTRFS_IOC_SCAN_DEV):

             /  btrfs_device_1 → loop0
   fs_device
             \  btrfs_device_2 → loop1
2. mount /dev/loop0 /mnt
   btrfs_open_devices
    btrfs_device_1->bdev_file = btrfs_get_bdev_and_sb(loop0)
    btrfs_device_2->bdev_file = btrfs_get_bdev_and_sb(loop1)
   btrfs_fill_super
    open_ctree
     fail: btrfs_close_devices // -ENOMEM
	    btrfs_close_bdev(btrfs_device_1)
             fput(btrfs_device_1->bdev_file)
	      // btrfs_device_1->bdev_file is freed
	    btrfs_close_bdev(btrfs_device_2)
             fput(btrfs_device_2->bdev_file)

3. mount /dev/loop1 /mnt
   btrfs_open_devices
    btrfs_get_bdev_and_sb(&bdev_file)
     // EIO, btrfs_device_1->bdev_file is not assigned,
     // which points to a freed memory area
    btrfs_device_2->bdev_file = btrfs_get_bdev_and_sb(loop1)
   btrfs_fill_super
    open_ctree
     btrfs_free_extra_devids
      if (btrfs_device_1->bdev_file)
       fput(btrfs_device_1->bdev_file) // UAF !

Fix it by setting 'device->bdev_file' as 'NULL' after closing the
btrfs_device in btrfs_close_one_device().

Fixes: 14238819 ("btrfs: do not background blkdev_put()")
CC: stable@vger.kernel.org # 4.19+
Link: https://bugzilla.kernel.org/show_bug.cgi?id=219408


Signed-off-by: default avatarZhihao Cheng <chengzhihao1@huawei.com>
Reviewed-by: default avatarDavid Sterba <dsterba@suse.com>
Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
Conflicts:
	fs/btrfs/volumes.c
[Not merge mainline commit 9ae061cf2a46 ("btrfs: port device access to file")]
Signed-off-by: default avatarLong Li <leo.lilong@huawei.com>
parent 8a039651
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -1143,6 +1143,7 @@ static void btrfs_close_one_device(struct btrfs_device *device)
	if (device->bdev) {
		fs_devices->open_devices--;
		device->bdev = NULL;
		device->bdev_handle = NULL;
	}
	clear_bit(BTRFS_DEV_STATE_WRITEABLE, &device->dev_state);
	btrfs_destroy_dev_zone_info(device);