Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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: 3e2cb9ee76c2 ("block: add IOC_PR_READ_RESERVATION ioctl")
Fixes: 22a1ffea5f80 ("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>

authored by

Stefan Hajnoczi and committed by
Jens Axboe
5b88af71 2ebc8d60

+23 -11
+23 -11
block/ioctl.c
··· 318 318 EXPORT_SYMBOL(blkdev_compat_ptr_ioctl); 319 319 #endif 320 320 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) 322 328 { 323 329 /* no sense to make reservations for partitions */ 324 330 if (bdev_is_partition(bdev)) ··· 332 326 333 327 if (capable(CAP_SYS_ADMIN)) 334 328 return true; 329 + 335 330 /* 336 - * Only allow unprivileged reservations if the file descriptor is open 337 - * for writing. 331 + * Only allow unprivileged reservation _out_ commands if the file 332 + * descriptor is open for writing. Allow reservation _in_ commands if 333 + * the file descriptor is open for reading since they do not modify the 334 + * device. 338 335 */ 339 - return mode & BLK_OPEN_WRITE; 336 + if (dir == PR_IN) 337 + return mode & BLK_OPEN_READ; 338 + else 339 + return mode & BLK_OPEN_WRITE; 340 340 } 341 341 342 342 static int blkdev_pr_register(struct block_device *bdev, blk_mode_t mode, ··· 351 339 const struct pr_ops *ops = bdev->bd_disk->fops->pr_ops; 352 340 struct pr_registration reg; 353 341 354 - if (!blkdev_pr_allowed(bdev, mode)) 342 + if (!blkdev_pr_allowed(bdev, mode, PR_OUT)) 355 343 return -EPERM; 356 344 if (!ops || !ops->pr_register) 357 345 return -EOPNOTSUPP; ··· 369 357 const struct pr_ops *ops = bdev->bd_disk->fops->pr_ops; 370 358 struct pr_reservation rsv; 371 359 372 - if (!blkdev_pr_allowed(bdev, mode)) 360 + if (!blkdev_pr_allowed(bdev, mode, PR_OUT)) 373 361 return -EPERM; 374 362 if (!ops || !ops->pr_reserve) 375 363 return -EOPNOTSUPP; ··· 387 375 const struct pr_ops *ops = bdev->bd_disk->fops->pr_ops; 388 376 struct pr_reservation rsv; 389 377 390 - if (!blkdev_pr_allowed(bdev, mode)) 378 + if (!blkdev_pr_allowed(bdev, mode, PR_OUT)) 391 379 return -EPERM; 392 380 if (!ops || !ops->pr_release) 393 381 return -EOPNOTSUPP; ··· 405 393 const struct pr_ops *ops = bdev->bd_disk->fops->pr_ops; 406 394 struct pr_preempt p; 407 395 408 - if (!blkdev_pr_allowed(bdev, mode)) 396 + if (!blkdev_pr_allowed(bdev, mode, PR_OUT)) 409 397 return -EPERM; 410 398 if (!ops || !ops->pr_preempt) 411 399 return -EOPNOTSUPP; ··· 423 411 const struct pr_ops *ops = bdev->bd_disk->fops->pr_ops; 424 412 struct pr_clear c; 425 413 426 - if (!blkdev_pr_allowed(bdev, mode)) 414 + if (!blkdev_pr_allowed(bdev, mode, PR_OUT)) 427 415 return -EPERM; 428 416 if (!ops || !ops->pr_clear) 429 417 return -EOPNOTSUPP; ··· 446 434 size_t keys_copy_len; 447 435 int ret; 448 436 449 - if (!blkdev_pr_allowed(bdev, mode)) 437 + if (!blkdev_pr_allowed(bdev, mode, PR_IN)) 450 438 return -EPERM; 451 439 if (!ops || !ops->pr_read_keys) 452 440 return -EOPNOTSUPP; ··· 498 486 struct pr_read_reservation out = {}; 499 487 int ret; 500 488 501 - if (!blkdev_pr_allowed(bdev, mode)) 489 + if (!blkdev_pr_allowed(bdev, mode, PR_IN)) 502 490 return -EPERM; 503 491 if (!ops || !ops->pr_read_reservation) 504 492 return -EOPNOTSUPP;