Skip to content

Commit 9a72a02

Browse files
lostjeffleaxboe
authored andcommitted
block: fine-granular CAP_SYS_ADMIN for Persistent Reservation
Allow of unprivileged Persistent Reservation operations on devices if the write permission check on the device node has passed. brw-rw---- 1 root disk 259, 0 Jun 13 07:09 /dev/nvme0n1 In the example above, the "disk" group of nvme0n1 is also allowed to make reservations on the device even without CAP_SYS_ADMIN. Signed-off-by: Jingbo Xu <[email protected]> Reviewed-by: Christoph Hellwig <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Jens Axboe <[email protected]>
1 parent 1262962 commit 9a72a02

File tree

1 file changed

+22
-19
lines changed

1 file changed

+22
-19
lines changed

block/ioctl.c

Lines changed: 22 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -254,25 +254,28 @@ int blkdev_compat_ptr_ioctl(struct block_device *bdev, blk_mode_t mode,
254254
EXPORT_SYMBOL(blkdev_compat_ptr_ioctl);
255255
#endif
256256

257-
static bool blkdev_pr_allowed(struct block_device *bdev)
257+
static bool blkdev_pr_allowed(struct block_device *bdev, blk_mode_t mode)
258258
{
259259
/* no sense to make reservations for partitions */
260260
if (bdev_is_partition(bdev))
261261
return false;
262262

263263
if (capable(CAP_SYS_ADMIN))
264264
return true;
265-
266-
return false;
265+
/*
266+
* Only allow unprivileged reservations if the file descriptor is open
267+
* for writing.
268+
*/
269+
return mode & BLK_OPEN_WRITE;
267270
}
268271

269-
static int blkdev_pr_register(struct block_device *bdev,
272+
static int blkdev_pr_register(struct block_device *bdev, blk_mode_t mode,
270273
struct pr_registration __user *arg)
271274
{
272275
const struct pr_ops *ops = bdev->bd_disk->fops->pr_ops;
273276
struct pr_registration reg;
274277

275-
if (!blkdev_pr_allowed(bdev))
278+
if (!blkdev_pr_allowed(bdev, mode))
276279
return -EPERM;
277280
if (!ops || !ops->pr_register)
278281
return -EOPNOTSUPP;
@@ -284,13 +287,13 @@ static int blkdev_pr_register(struct block_device *bdev,
284287
return ops->pr_register(bdev, reg.old_key, reg.new_key, reg.flags);
285288
}
286289

287-
static int blkdev_pr_reserve(struct block_device *bdev,
290+
static int blkdev_pr_reserve(struct block_device *bdev, blk_mode_t mode,
288291
struct pr_reservation __user *arg)
289292
{
290293
const struct pr_ops *ops = bdev->bd_disk->fops->pr_ops;
291294
struct pr_reservation rsv;
292295

293-
if (!blkdev_pr_allowed(bdev))
296+
if (!blkdev_pr_allowed(bdev, mode))
294297
return -EPERM;
295298
if (!ops || !ops->pr_reserve)
296299
return -EOPNOTSUPP;
@@ -302,13 +305,13 @@ static int blkdev_pr_reserve(struct block_device *bdev,
302305
return ops->pr_reserve(bdev, rsv.key, rsv.type, rsv.flags);
303306
}
304307

305-
static int blkdev_pr_release(struct block_device *bdev,
308+
static int blkdev_pr_release(struct block_device *bdev, blk_mode_t mode,
306309
struct pr_reservation __user *arg)
307310
{
308311
const struct pr_ops *ops = bdev->bd_disk->fops->pr_ops;
309312
struct pr_reservation rsv;
310313

311-
if (!blkdev_pr_allowed(bdev))
314+
if (!blkdev_pr_allowed(bdev, mode))
312315
return -EPERM;
313316
if (!ops || !ops->pr_release)
314317
return -EOPNOTSUPP;
@@ -320,13 +323,13 @@ static int blkdev_pr_release(struct block_device *bdev,
320323
return ops->pr_release(bdev, rsv.key, rsv.type);
321324
}
322325

323-
static int blkdev_pr_preempt(struct block_device *bdev,
326+
static int blkdev_pr_preempt(struct block_device *bdev, blk_mode_t mode,
324327
struct pr_preempt __user *arg, bool abort)
325328
{
326329
const struct pr_ops *ops = bdev->bd_disk->fops->pr_ops;
327330
struct pr_preempt p;
328331

329-
if (!blkdev_pr_allowed(bdev))
332+
if (!blkdev_pr_allowed(bdev, mode))
330333
return -EPERM;
331334
if (!ops || !ops->pr_preempt)
332335
return -EOPNOTSUPP;
@@ -338,13 +341,13 @@ static int blkdev_pr_preempt(struct block_device *bdev,
338341
return ops->pr_preempt(bdev, p.old_key, p.new_key, p.type, abort);
339342
}
340343

341-
static int blkdev_pr_clear(struct block_device *bdev,
344+
static int blkdev_pr_clear(struct block_device *bdev, blk_mode_t mode,
342345
struct pr_clear __user *arg)
343346
{
344347
const struct pr_ops *ops = bdev->bd_disk->fops->pr_ops;
345348
struct pr_clear c;
346349

347-
if (!blkdev_pr_allowed(bdev))
350+
if (!blkdev_pr_allowed(bdev, mode))
348351
return -EPERM;
349352
if (!ops || !ops->pr_clear)
350353
return -EOPNOTSUPP;
@@ -546,17 +549,17 @@ static int blkdev_common_ioctl(struct block_device *bdev, blk_mode_t mode,
546549
case BLKTRACETEARDOWN:
547550
return blk_trace_ioctl(bdev, cmd, argp);
548551
case IOC_PR_REGISTER:
549-
return blkdev_pr_register(bdev, argp);
552+
return blkdev_pr_register(bdev, mode, argp);
550553
case IOC_PR_RESERVE:
551-
return blkdev_pr_reserve(bdev, argp);
554+
return blkdev_pr_reserve(bdev, mode, argp);
552555
case IOC_PR_RELEASE:
553-
return blkdev_pr_release(bdev, argp);
556+
return blkdev_pr_release(bdev, mode, argp);
554557
case IOC_PR_PREEMPT:
555-
return blkdev_pr_preempt(bdev, argp, false);
558+
return blkdev_pr_preempt(bdev, mode, argp, false);
556559
case IOC_PR_PREEMPT_ABORT:
557-
return blkdev_pr_preempt(bdev, argp, true);
560+
return blkdev_pr_preempt(bdev, mode, argp, true);
558561
case IOC_PR_CLEAR:
559-
return blkdev_pr_clear(bdev, argp);
562+
return blkdev_pr_clear(bdev, mode, argp);
560563
default:
561564
return -ENOIOCTLCMD;
562565
}

0 commit comments

Comments
 (0)