• Filipe David Borba Manana's avatar
    Btrfs: fix race conditions in BTRFS_IOC_FS_INFO ioctl · f7171750
    Filipe David Borba Manana authored
    The handler for the ioctl BTRFS_IOC_FS_INFO was reading the
    number of devices before acquiring the device list mutex.
    
    This could lead to inconsistent results because the update of
    the device list and the number of devices counter (amongst other
    counters related to the device list) are updated in volumes.c
    while holding the device list mutex - except for 2 places, one
    was volumes.c:btrfs_prepare_sprout() and the other was
    volumes.c:device_list_add().
    
    For example, if we have 2 devices, with IDs 1 and 2 and then add
    a new device, with ID 3, and while adding the device is in progress
    an BTRFS_IOC_FS_INFO ioctl arrives, it could return a number of
    devices of 2 and a max dev id of 3. This would be incorrect.
    
    Also, this ioctl handler was reading the fsid while it can be
    updated concurrently. This can happen when while a new device is
    being added and the current filesystem is in seeding mode.
    Example:
    
    $ mkfs.btrfs -f /dev/sdb1
    $ mkfs.btrfs -f /dev/sdb2
    $ btrfstune -S 1 /dev/sdb1
    $ mount /dev/sdb1 /mnt/test
    $ btrfs device add /dev/sdb2 /mnt/test
    
    If during the last step a BTRFS_IOC_FS_INFO ioctl was requested, it
    could read an fsid that was never valid (some bits part of the old
    fsid and others part of the new fsid). Also, it could read a number
    of devices that doesn't match the number of devices in the list and
    the max device id, as explained before.
    Signed-off-by: default avatarFilipe David Borba Manana <fdmanana@gmail.com>
    Signed-off-by: default avatarJosef Bacik <jbacik@fusionio.com>
    Signed-off-by: default avatarChris Mason <chris.mason@fusionio.com>
    f7171750
volumes.c 160 KB