block: disallow Persistent Reservation on partitions
authorJingbo Xu <jefflexu@linux.alibaba.com>
Tue, 13 Jun 2023 08:40:07 +0000 (16:40 +0800)
committerJens Axboe <axboe@kernel.dk>
Tue, 20 Jun 2023 18:49:23 +0000 (12:49 -0600)
Refuse Persistent Reservation operations on partitions as reservation
on partitions doesn't make sense.

Besides, introduce blkdev_pr_allowed() helper, where more policies could
be placed here later.

Signed-off-by: Jingbo Xu <jefflexu@linux.alibaba.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Link: https://lore.kernel.org/r/20230613084008.93795-2-jefflexu@linux.alibaba.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
block/ioctl.c

index 61bb94fd42818727d2011ca3685860d42129e774..c75299006bdd37b6e20d50af4782b7f7de810334 100644 (file)
@@ -254,13 +254,25 @@ int blkdev_compat_ptr_ioctl(struct block_device *bdev, blk_mode_t mode,
 EXPORT_SYMBOL(blkdev_compat_ptr_ioctl);
 #endif
 
+static bool blkdev_pr_allowed(struct block_device *bdev)
+{
+       /* no sense to make reservations for partitions */
+       if (bdev_is_partition(bdev))
+               return false;
+
+       if (capable(CAP_SYS_ADMIN))
+               return true;
+
+       return false;
+}
+
 static int blkdev_pr_register(struct block_device *bdev,
                struct pr_registration __user *arg)
 {
        const struct pr_ops *ops = bdev->bd_disk->fops->pr_ops;
        struct pr_registration reg;
 
-       if (!capable(CAP_SYS_ADMIN))
+       if (!blkdev_pr_allowed(bdev))
                return -EPERM;
        if (!ops || !ops->pr_register)
                return -EOPNOTSUPP;
@@ -278,7 +290,7 @@ static int blkdev_pr_reserve(struct block_device *bdev,
        const struct pr_ops *ops = bdev->bd_disk->fops->pr_ops;
        struct pr_reservation rsv;
 
-       if (!capable(CAP_SYS_ADMIN))
+       if (!blkdev_pr_allowed(bdev))
                return -EPERM;
        if (!ops || !ops->pr_reserve)
                return -EOPNOTSUPP;
@@ -296,7 +308,7 @@ static int blkdev_pr_release(struct block_device *bdev,
        const struct pr_ops *ops = bdev->bd_disk->fops->pr_ops;
        struct pr_reservation rsv;
 
-       if (!capable(CAP_SYS_ADMIN))
+       if (!blkdev_pr_allowed(bdev))
                return -EPERM;
        if (!ops || !ops->pr_release)
                return -EOPNOTSUPP;
@@ -314,7 +326,7 @@ static int blkdev_pr_preempt(struct block_device *bdev,
        const struct pr_ops *ops = bdev->bd_disk->fops->pr_ops;
        struct pr_preempt p;
 
-       if (!capable(CAP_SYS_ADMIN))
+       if (!blkdev_pr_allowed(bdev))
                return -EPERM;
        if (!ops || !ops->pr_preempt)
                return -EOPNOTSUPP;
@@ -332,7 +344,7 @@ static int blkdev_pr_clear(struct block_device *bdev,
        const struct pr_ops *ops = bdev->bd_disk->fops->pr_ops;
        struct pr_clear c;
 
-       if (!capable(CAP_SYS_ADMIN))
+       if (!blkdev_pr_allowed(bdev))
                return -EPERM;
        if (!ops || !ops->pr_clear)
                return -EOPNOTSUPP;