diff options
Diffstat (limited to 'block/scsi_ioctl.c')
-rw-r--r-- | block/scsi_ioctl.c | 33 |
1 files changed, 14 insertions, 19 deletions
diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c index c34272a348fe..5963cf91a3a0 100644 --- a/block/scsi_ioctl.c +++ b/block/scsi_ioctl.c | |||
@@ -190,12 +190,11 @@ void blk_set_cmd_filter_defaults(struct blk_cmd_filter *filter) | |||
190 | EXPORT_SYMBOL_GPL(blk_set_cmd_filter_defaults); | 190 | EXPORT_SYMBOL_GPL(blk_set_cmd_filter_defaults); |
191 | 191 | ||
192 | static int blk_fill_sghdr_rq(struct request_queue *q, struct request *rq, | 192 | static int blk_fill_sghdr_rq(struct request_queue *q, struct request *rq, |
193 | struct sg_io_hdr *hdr, struct file *file) | 193 | struct sg_io_hdr *hdr, fmode_t mode) |
194 | { | 194 | { |
195 | if (copy_from_user(rq->cmd, hdr->cmdp, hdr->cmd_len)) | 195 | if (copy_from_user(rq->cmd, hdr->cmdp, hdr->cmd_len)) |
196 | return -EFAULT; | 196 | return -EFAULT; |
197 | if (blk_verify_command(&q->cmd_filter, rq->cmd, | 197 | if (blk_verify_command(&q->cmd_filter, rq->cmd, mode & FMODE_WRITE)) |
198 | file->f_mode & FMODE_WRITE)) | ||
199 | return -EPERM; | 198 | return -EPERM; |
200 | 199 | ||
201 | /* | 200 | /* |
@@ -260,8 +259,8 @@ static int blk_complete_sghdr_rq(struct request *rq, struct sg_io_hdr *hdr, | |||
260 | return r; | 259 | return r; |
261 | } | 260 | } |
262 | 261 | ||
263 | static int sg_io(struct file *file, struct request_queue *q, | 262 | static int sg_io(struct request_queue *q, struct gendisk *bd_disk, |
264 | struct gendisk *bd_disk, struct sg_io_hdr *hdr) | 263 | struct sg_io_hdr *hdr, fmode_t mode) |
265 | { | 264 | { |
266 | unsigned long start_time; | 265 | unsigned long start_time; |
267 | int writing = 0, ret = 0; | 266 | int writing = 0, ret = 0; |
@@ -293,7 +292,7 @@ static int sg_io(struct file *file, struct request_queue *q, | |||
293 | if (!rq) | 292 | if (!rq) |
294 | return -ENOMEM; | 293 | return -ENOMEM; |
295 | 294 | ||
296 | if (blk_fill_sghdr_rq(q, rq, hdr, file)) { | 295 | if (blk_fill_sghdr_rq(q, rq, hdr, mode)) { |
297 | blk_put_request(rq); | 296 | blk_put_request(rq); |
298 | return -EFAULT; | 297 | return -EFAULT; |
299 | } | 298 | } |
@@ -380,11 +379,11 @@ out: | |||
380 | * bytes in one int) where the lowest byte is the SCSI status. | 379 | * bytes in one int) where the lowest byte is the SCSI status. |
381 | */ | 380 | */ |
382 | #define OMAX_SB_LEN 16 /* For backward compatibility */ | 381 | #define OMAX_SB_LEN 16 /* For backward compatibility */ |
383 | int sg_scsi_ioctl(struct file *file, struct request_queue *q, | 382 | int sg_scsi_ioctl(struct request_queue *q, struct gendisk *disk, fmode_t mode, |
384 | struct gendisk *disk, struct scsi_ioctl_command __user *sic) | 383 | struct scsi_ioctl_command __user *sic) |
385 | { | 384 | { |
386 | struct request *rq; | 385 | struct request *rq; |
387 | int err, write_perm = 0; | 386 | int err; |
388 | unsigned int in_len, out_len, bytes, opcode, cmdlen; | 387 | unsigned int in_len, out_len, bytes, opcode, cmdlen; |
389 | char *buffer = NULL, sense[SCSI_SENSE_BUFFERSIZE]; | 388 | char *buffer = NULL, sense[SCSI_SENSE_BUFFERSIZE]; |
390 | 389 | ||
@@ -426,11 +425,7 @@ int sg_scsi_ioctl(struct file *file, struct request_queue *q, | |||
426 | if (in_len && copy_from_user(buffer, sic->data + cmdlen, in_len)) | 425 | if (in_len && copy_from_user(buffer, sic->data + cmdlen, in_len)) |
427 | goto error; | 426 | goto error; |
428 | 427 | ||
429 | /* scsi_ioctl passes NULL */ | 428 | err = blk_verify_command(&q->cmd_filter, rq->cmd, mode & FMODE_WRITE); |
430 | if (file && (file->f_mode & FMODE_WRITE)) | ||
431 | write_perm = 1; | ||
432 | |||
433 | err = blk_verify_command(&q->cmd_filter, rq->cmd, write_perm); | ||
434 | if (err) | 429 | if (err) |
435 | goto error; | 430 | goto error; |
436 | 431 | ||
@@ -522,8 +517,8 @@ static inline int blk_send_start_stop(struct request_queue *q, | |||
522 | return __blk_send_generic(q, bd_disk, GPCMD_START_STOP_UNIT, data); | 517 | return __blk_send_generic(q, bd_disk, GPCMD_START_STOP_UNIT, data); |
523 | } | 518 | } |
524 | 519 | ||
525 | int scsi_cmd_ioctl(struct file *file, struct request_queue *q, | 520 | int scsi_cmd_ioctl(struct request_queue *q, struct gendisk *bd_disk, fmode_t mode, |
526 | struct gendisk *bd_disk, unsigned int cmd, void __user *arg) | 521 | unsigned int cmd, void __user *arg) |
527 | { | 522 | { |
528 | int err; | 523 | int err; |
529 | 524 | ||
@@ -564,7 +559,7 @@ int scsi_cmd_ioctl(struct file *file, struct request_queue *q, | |||
564 | err = -EFAULT; | 559 | err = -EFAULT; |
565 | if (copy_from_user(&hdr, arg, sizeof(hdr))) | 560 | if (copy_from_user(&hdr, arg, sizeof(hdr))) |
566 | break; | 561 | break; |
567 | err = sg_io(file, q, bd_disk, &hdr); | 562 | err = sg_io(q, bd_disk, &hdr, mode); |
568 | if (err == -EFAULT) | 563 | if (err == -EFAULT) |
569 | break; | 564 | break; |
570 | 565 | ||
@@ -612,7 +607,7 @@ int scsi_cmd_ioctl(struct file *file, struct request_queue *q, | |||
612 | hdr.cmdp = ((struct cdrom_generic_command __user*) arg)->cmd; | 607 | hdr.cmdp = ((struct cdrom_generic_command __user*) arg)->cmd; |
613 | hdr.cmd_len = sizeof(cgc.cmd); | 608 | hdr.cmd_len = sizeof(cgc.cmd); |
614 | 609 | ||
615 | err = sg_io(file, q, bd_disk, &hdr); | 610 | err = sg_io(q, bd_disk, &hdr, mode); |
616 | if (err == -EFAULT) | 611 | if (err == -EFAULT) |
617 | break; | 612 | break; |
618 | 613 | ||
@@ -636,7 +631,7 @@ int scsi_cmd_ioctl(struct file *file, struct request_queue *q, | |||
636 | if (!arg) | 631 | if (!arg) |
637 | break; | 632 | break; |
638 | 633 | ||
639 | err = sg_scsi_ioctl(file, q, bd_disk, arg); | 634 | err = sg_scsi_ioctl(q, bd_disk, mode, arg); |
640 | break; | 635 | break; |
641 | case CDROMCLOSETRAY: | 636 | case CDROMCLOSETRAY: |
642 | err = blk_send_start_stop(q, bd_disk, 0x03); | 637 | err = blk_send_start_stop(q, bd_disk, 0x03); |