Hi

If dm_get_device spuriously closes a device that was already open, it is a 
bug in dm_get_device and it should be fixed there.

Note that we got 3 patches for this syzbot warning from 3 different 
people. Please, cooperate next time and send just one patch.

Mikulas


On Mon, 26 Oct 2026, Eduard Zateev wrote:

> From: angel <[email protected]>
> 
> The thin-pool target rejects identical argument strings, but two names for
> the same block device bypass the check. In read-only metadata mode, opening
> metadata first and data with write mode invokes dm_get_device()
> upgrade_mode().
> That swaps and frees the old dm_dev while pool_ctr retains metadata_dev,
> causing a slab-use-after-free when __pool_find() reads metadata_dev->bdev.
> 
> Open the data device before metadata so an alias cannot trigger a mode
> upgrade between the two references. Compare the opened block devices
> and reject aliases before using either device. Adjust the error paths to
> release the devices in the matching order.
> 
> Reported-by: [email protected]
> Closes: https://syzkaller.appspot.com/bug?extid=83827f9a59abe148bff4
> Fixes: 70de2cbda8a5 ("dm thin: add sanity checks to thin-pool and external 
> snapshot creation")
> Signed-off-by: Eduard Zateev <[email protected]>
> ---
>  drivers/md/dm-thin.c | 21 ++++++++++++++-------
>  1 file changed, 14 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c
> index 358ed77ff..0899cbaf9 100644
> --- a/drivers/md/dm-thin.c
> +++ b/drivers/md/dm-thin.c
> @@ -3326,17 +3326,24 @@ static int pool_ctr(struct dm_target *ti, unsigned 
> int argc, char **argv)
>  
>       metadata_mode = BLK_OPEN_READ |
>               ((pf.mode == PM_READ_ONLY) ? 0 : BLK_OPEN_WRITE);
> +     r = dm_get_device(ti, argv[1], BLK_OPEN_READ | BLK_OPEN_WRITE, 
> &data_dev);
> +     if (r) {
> +             ti->error = "Error getting data device";
> +             goto out_unlock;
> +     }
> +
>       r = dm_get_device(ti, argv[0], metadata_mode, &metadata_dev);
>       if (r) {
>               ti->error = "Error opening metadata block device";
> -             goto out_unlock;
> +             goto out_data;
>       }
>       warn_if_metadata_device_too_big(metadata_dev->bdev);
>  
> -     r = dm_get_device(ti, argv[1], BLK_OPEN_READ | BLK_OPEN_WRITE, 
> &data_dev);
> -     if (r) {
> -             ti->error = "Error getting data device";
> -             goto out_metadata;
> +     /* make sure metadata and data are different devices */
> +     if (metadata_dev->bdev == data_dev->bdev) {
> +             ti->error = "Error setting metadata or data device";
> +             r = -EINVAL;
> +             goto out;
>       }
>  
>       if (kstrtoul(argv[2], 10, &block_size) || !block_size ||
> @@ -3426,9 +3433,9 @@ static int pool_ctr(struct dm_target *ti, unsigned int 
> argc, char **argv)
>  out_free_pt:
>       kfree(pt);
>  out:
> -     dm_put_device(ti, data_dev);
> -out_metadata:
>       dm_put_device(ti, metadata_dev);
> +out_data:
> +     dm_put_device(ti, data_dev);
>  out_unlock:
>       mutex_unlock(&dm_thin_pool_table.mutex);
>  
> 
> base-commit: 21a7f44fd0765fcc5194130b28767786eba1d1e7
> -- 
> 2.56.0
> 


Reply via email to