@@ -254,25 +254,28 @@ int blkdev_compat_ptr_ioctl(struct block_device *bdev, blk_mode_t mode,
254
254
EXPORT_SYMBOL (blkdev_compat_ptr_ioctl );
255
255
#endif
256
256
257
- static bool blkdev_pr_allowed (struct block_device * bdev )
257
+ static bool blkdev_pr_allowed (struct block_device * bdev , blk_mode_t mode )
258
258
{
259
259
/* no sense to make reservations for partitions */
260
260
if (bdev_is_partition (bdev ))
261
261
return false;
262
262
263
263
if (capable (CAP_SYS_ADMIN ))
264
264
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 ;
267
270
}
268
271
269
- static int blkdev_pr_register (struct block_device * bdev ,
272
+ static int blkdev_pr_register (struct block_device * bdev , blk_mode_t mode ,
270
273
struct pr_registration __user * arg )
271
274
{
272
275
const struct pr_ops * ops = bdev -> bd_disk -> fops -> pr_ops ;
273
276
struct pr_registration reg ;
274
277
275
- if (!blkdev_pr_allowed (bdev ))
278
+ if (!blkdev_pr_allowed (bdev , mode ))
276
279
return - EPERM ;
277
280
if (!ops || !ops -> pr_register )
278
281
return - EOPNOTSUPP ;
@@ -284,13 +287,13 @@ static int blkdev_pr_register(struct block_device *bdev,
284
287
return ops -> pr_register (bdev , reg .old_key , reg .new_key , reg .flags );
285
288
}
286
289
287
- static int blkdev_pr_reserve (struct block_device * bdev ,
290
+ static int blkdev_pr_reserve (struct block_device * bdev , blk_mode_t mode ,
288
291
struct pr_reservation __user * arg )
289
292
{
290
293
const struct pr_ops * ops = bdev -> bd_disk -> fops -> pr_ops ;
291
294
struct pr_reservation rsv ;
292
295
293
- if (!blkdev_pr_allowed (bdev ))
296
+ if (!blkdev_pr_allowed (bdev , mode ))
294
297
return - EPERM ;
295
298
if (!ops || !ops -> pr_reserve )
296
299
return - EOPNOTSUPP ;
@@ -302,13 +305,13 @@ static int blkdev_pr_reserve(struct block_device *bdev,
302
305
return ops -> pr_reserve (bdev , rsv .key , rsv .type , rsv .flags );
303
306
}
304
307
305
- static int blkdev_pr_release (struct block_device * bdev ,
308
+ static int blkdev_pr_release (struct block_device * bdev , blk_mode_t mode ,
306
309
struct pr_reservation __user * arg )
307
310
{
308
311
const struct pr_ops * ops = bdev -> bd_disk -> fops -> pr_ops ;
309
312
struct pr_reservation rsv ;
310
313
311
- if (!blkdev_pr_allowed (bdev ))
314
+ if (!blkdev_pr_allowed (bdev , mode ))
312
315
return - EPERM ;
313
316
if (!ops || !ops -> pr_release )
314
317
return - EOPNOTSUPP ;
@@ -320,13 +323,13 @@ static int blkdev_pr_release(struct block_device *bdev,
320
323
return ops -> pr_release (bdev , rsv .key , rsv .type );
321
324
}
322
325
323
- static int blkdev_pr_preempt (struct block_device * bdev ,
326
+ static int blkdev_pr_preempt (struct block_device * bdev , blk_mode_t mode ,
324
327
struct pr_preempt __user * arg , bool abort )
325
328
{
326
329
const struct pr_ops * ops = bdev -> bd_disk -> fops -> pr_ops ;
327
330
struct pr_preempt p ;
328
331
329
- if (!blkdev_pr_allowed (bdev ))
332
+ if (!blkdev_pr_allowed (bdev , mode ))
330
333
return - EPERM ;
331
334
if (!ops || !ops -> pr_preempt )
332
335
return - EOPNOTSUPP ;
@@ -338,13 +341,13 @@ static int blkdev_pr_preempt(struct block_device *bdev,
338
341
return ops -> pr_preempt (bdev , p .old_key , p .new_key , p .type , abort );
339
342
}
340
343
341
- static int blkdev_pr_clear (struct block_device * bdev ,
344
+ static int blkdev_pr_clear (struct block_device * bdev , blk_mode_t mode ,
342
345
struct pr_clear __user * arg )
343
346
{
344
347
const struct pr_ops * ops = bdev -> bd_disk -> fops -> pr_ops ;
345
348
struct pr_clear c ;
346
349
347
- if (!blkdev_pr_allowed (bdev ))
350
+ if (!blkdev_pr_allowed (bdev , mode ))
348
351
return - EPERM ;
349
352
if (!ops || !ops -> pr_clear )
350
353
return - EOPNOTSUPP ;
@@ -546,17 +549,17 @@ static int blkdev_common_ioctl(struct block_device *bdev, blk_mode_t mode,
546
549
case BLKTRACETEARDOWN :
547
550
return blk_trace_ioctl (bdev , cmd , argp );
548
551
case IOC_PR_REGISTER :
549
- return blkdev_pr_register (bdev , argp );
552
+ return blkdev_pr_register (bdev , mode , argp );
550
553
case IOC_PR_RESERVE :
551
- return blkdev_pr_reserve (bdev , argp );
554
+ return blkdev_pr_reserve (bdev , mode , argp );
552
555
case IOC_PR_RELEASE :
553
- return blkdev_pr_release (bdev , argp );
556
+ return blkdev_pr_release (bdev , mode , argp );
554
557
case IOC_PR_PREEMPT :
555
- return blkdev_pr_preempt (bdev , argp , false);
558
+ return blkdev_pr_preempt (bdev , mode , argp , false);
556
559
case IOC_PR_PREEMPT_ABORT :
557
- return blkdev_pr_preempt (bdev , argp , true);
560
+ return blkdev_pr_preempt (bdev , mode , argp , true);
558
561
case IOC_PR_CLEAR :
559
- return blkdev_pr_clear (bdev , argp );
562
+ return blkdev_pr_clear (bdev , mode , argp );
560
563
default :
561
564
return - ENOIOCTLCMD ;
562
565
}
0 commit comments