History

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.

Stefan Hajnoczi committed 9 months ago

Commit 5b88af71 parent 2ebc8d61 file · +23 −11Browse files

Unified · Split

block/ioctl.c+23−11
@@ -318,7 +318,13 @@ int blkdev_compat_ptr_ioctl(struct block_device *bdev, blk_mode_t mode, · 317 unmodified lines
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))
@@ -326,11 +332,17 @@ static bool blkdev_pr_allowed(struct block_device *bdev, blk_mode_t mode) · 1 unmodified line
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, · 2 unmodified lines
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, · 11 unmodified lines
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, · 11 unmodified lines
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, · 11 unmodified lines
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, · 11 unmodified lines
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, · 16 unmodified lines
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, · 45 unmodified lines
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;

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t