Skip to content

Commit 5b88af7

Browse files
stefanhaRHaxboe
authored andcommitted
block: allow IOC_PR_READ_* ioctls with BLK_OPEN_READ
The recently added IOC_PR_READ_* ioctls require the same BLK_OPEN_WRITE permission as the older persistent reservation ioctls. This has the drawback that udev triggers when the file descriptor is closed, resulting in unnecessary activity like scanning partitions even though these read-only ioctls do not modify the device. Change IOC_PR_READ_KEYS and IOC_PR_READ_RESERVATION to require BLK_OPEN_READ. This prevents unnecessary activity every time `blkpr --read-keys` or `blkpr --read-reservation` is invoked by shell scripts, for example. It is safe to reduce the permission requirement from BLK_OPEN_WRITE to BLK_OPEN_READ since these two ioctls do not modify the persistent reservation state. Userspace cannot use the information fetched by these ioctls to make changes to the device unless it later opens the device with BLK_OPEN_WRITE. Fixes: 3e2cb9e ("block: add IOC_PR_READ_RESERVATION ioctl") Fixes: 22a1ffe ("block: add IOC_PR_READ_KEYS ioctl") Cc: Christoph Hellwig <hch@lst.de> Cc: Martin Wilck <mwilck@suse.com> Cc: Benjamin Marzinski <bmarzins@redhat.com> Suggested-by: Hannes Reinecke <hare@suse.de> Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Jens Axboe <axboe@kernel.dk>
1 parent 2ebc8d6 commit 5b88af7

1 file changed

Lines changed: 23 additions & 11 deletions

File tree

block/ioctl.c

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -318,19 +318,31 @@ int blkdev_compat_ptr_ioctl(struct block_device *bdev, blk_mode_t mode,
318318
EXPORT_SYMBOL(blkdev_compat_ptr_ioctl);
319319
#endif
320320

321-
static bool blkdev_pr_allowed(struct block_device *bdev, blk_mode_t mode)
321+
enum pr_direction {
322+
PR_IN, /* read from device */
323+
PR_OUT, /* write to device */
324+
};
325+
326+
static bool blkdev_pr_allowed(struct block_device *bdev, blk_mode_t mode,
327+
enum pr_direction dir)
322328
{
323329
/* no sense to make reservations for partitions */
324330
if (bdev_is_partition(bdev))
325331
return false;
326332

327333
if (capable(CAP_SYS_ADMIN))
328334
return true;
335+
329336
/*
330-
* Only allow unprivileged reservations if the file descriptor is open
331-
* for writing.
337+
* Only allow unprivileged reservation _out_ commands if the file
338+
* descriptor is open for writing. Allow reservation _in_ commands if
339+
* the file descriptor is open for reading since they do not modify the
340+
* device.
332341
*/
333-
return mode & BLK_OPEN_WRITE;
342+
if (dir == PR_IN)
343+
return mode & BLK_OPEN_READ;
344+
else
345+
return mode & BLK_OPEN_WRITE;
334346
}
335347

336348
static int blkdev_pr_register(struct block_device *bdev, blk_mode_t mode,
@@ -339,7 +351,7 @@ static int blkdev_pr_register(struct block_device *bdev, blk_mode_t mode,
339351
const struct pr_ops *ops = bdev->bd_disk->fops->pr_ops;
340352
struct pr_registration reg;
341353

342-
if (!blkdev_pr_allowed(bdev, mode))
354+
if (!blkdev_pr_allowed(bdev, mode, PR_OUT))
343355
return -EPERM;
344356
if (!ops || !ops->pr_register)
345357
return -EOPNOTSUPP;
@@ -357,7 +369,7 @@ static int blkdev_pr_reserve(struct block_device *bdev, blk_mode_t mode,
357369
const struct pr_ops *ops = bdev->bd_disk->fops->pr_ops;
358370
struct pr_reservation rsv;
359371

360-
if (!blkdev_pr_allowed(bdev, mode))
372+
if (!blkdev_pr_allowed(bdev, mode, PR_OUT))
361373
return -EPERM;
362374
if (!ops || !ops->pr_reserve)
363375
return -EOPNOTSUPP;
@@ -375,7 +387,7 @@ static int blkdev_pr_release(struct block_device *bdev, blk_mode_t mode,
375387
const struct pr_ops *ops = bdev->bd_disk->fops->pr_ops;
376388
struct pr_reservation rsv;
377389

378-
if (!blkdev_pr_allowed(bdev, mode))
390+
if (!blkdev_pr_allowed(bdev, mode, PR_OUT))
379391
return -EPERM;
380392
if (!ops || !ops->pr_release)
381393
return -EOPNOTSUPP;
@@ -393,7 +405,7 @@ static int blkdev_pr_preempt(struct block_device *bdev, blk_mode_t mode,
393405
const struct pr_ops *ops = bdev->bd_disk->fops->pr_ops;
394406
struct pr_preempt p;
395407

396-
if (!blkdev_pr_allowed(bdev, mode))
408+
if (!blkdev_pr_allowed(bdev, mode, PR_OUT))
397409
return -EPERM;
398410
if (!ops || !ops->pr_preempt)
399411
return -EOPNOTSUPP;
@@ -411,7 +423,7 @@ static int blkdev_pr_clear(struct block_device *bdev, blk_mode_t mode,
411423
const struct pr_ops *ops = bdev->bd_disk->fops->pr_ops;
412424
struct pr_clear c;
413425

414-
if (!blkdev_pr_allowed(bdev, mode))
426+
if (!blkdev_pr_allowed(bdev, mode, PR_OUT))
415427
return -EPERM;
416428
if (!ops || !ops->pr_clear)
417429
return -EOPNOTSUPP;
@@ -434,7 +446,7 @@ static int blkdev_pr_read_keys(struct block_device *bdev, blk_mode_t mode,
434446
size_t keys_copy_len;
435447
int ret;
436448

437-
if (!blkdev_pr_allowed(bdev, mode))
449+
if (!blkdev_pr_allowed(bdev, mode, PR_IN))
438450
return -EPERM;
439451
if (!ops || !ops->pr_read_keys)
440452
return -EOPNOTSUPP;
@@ -486,7 +498,7 @@ static int blkdev_pr_read_reservation(struct block_device *bdev,
486498
struct pr_read_reservation out = {};
487499
int ret;
488500

489-
if (!blkdev_pr_allowed(bdev, mode))
501+
if (!blkdev_pr_allowed(bdev, mode, PR_IN))
490502
return -EPERM;
491503
if (!ops || !ops->pr_read_reservation)
492504
return -EOPNOTSUPP;

0 commit comments

Comments
 (0)