]> git.baikalelectronics.ru Git - kernel.git/commitdiff
btrfs: fix match incorrectly in dev_args_match_device
authorLiu Shixin <liushixin2@huawei.com>
Thu, 3 Nov 2022 08:33:01 +0000 (16:33 +0800)
committerDavid Sterba <dsterba@suse.com>
Mon, 7 Nov 2022 13:30:45 +0000 (14:30 +0100)
syzkaller found a failed assertion:

  assertion failed: (args->devid != (u64)-1) || args->missing, in fs/btrfs/volumes.c:6921

This can be triggered when we set devid to (u64)-1 by ioctl. In this
case, the match of devid will be skipped and the match of device may
succeed incorrectly.

Patch 562d7b1512f7 introduced this function which is used to match device.
This function contains two matching scenarios, we can distinguish them by
checking the value of args->missing rather than check whether args->devid
and args->uuid is default value.

Reported-by: syzbot+031687116258450f9853@syzkaller.appspotmail.com
Fixes: 562d7b1512f7 ("btrfs: handle device lookup with btrfs_dev_lookup_args")
CC: stable@vger.kernel.org # 5.16+
Reviewed-by: Nikolay Borisov <nborisov@suse.com>
Signed-off-by: Liu Shixin <liushixin2@huawei.com>
Signed-off-by: David Sterba <dsterba@suse.com>
fs/btrfs/volumes.c

index a8d4bc6a1937969fae3a89a1730abf930b63d304..f09d09c259f5fbcc5c378f944d8eae8b8dc884a1 100644 (file)
@@ -6918,18 +6918,18 @@ static bool dev_args_match_fs_devices(const struct btrfs_dev_lookup_args *args,
 static bool dev_args_match_device(const struct btrfs_dev_lookup_args *args,
                                  const struct btrfs_device *device)
 {
-       ASSERT((args->devid != (u64)-1) || args->missing);
+       if (args->missing) {
+               if (test_bit(BTRFS_DEV_STATE_IN_FS_METADATA, &device->dev_state) &&
+                   !device->bdev)
+                       return true;
+               return false;
+       }
 
-       if ((args->devid != (u64)-1) && device->devid != args->devid)
+       if (device->devid != args->devid)
                return false;
        if (args->uuid && memcmp(device->uuid, args->uuid, BTRFS_UUID_SIZE) != 0)
                return false;
-       if (!args->missing)
-               return true;
-       if (test_bit(BTRFS_DEV_STATE_IN_FS_METADATA, &device->dev_state) &&
-           !device->bdev)
-               return true;
-       return false;
+       return true;
 }
 
 /*