diff options
Diffstat (limited to 'block/bsg.c')
-rw-r--r-- | block/bsg.c | 38 |
1 files changed, 27 insertions, 11 deletions
diff --git a/block/bsg.c b/block/bsg.c index 7c59ffaedfe0..0b3b282f0384 100644 --- a/block/bsg.c +++ b/block/bsg.c | |||
@@ -45,11 +45,12 @@ struct bsg_device { | |||
45 | char name[BUS_ID_SIZE]; | 45 | char name[BUS_ID_SIZE]; |
46 | int max_queue; | 46 | int max_queue; |
47 | unsigned long flags; | 47 | unsigned long flags; |
48 | struct blk_scsi_cmd_filter *cmd_filter; | ||
49 | mode_t *f_mode; | ||
48 | }; | 50 | }; |
49 | 51 | ||
50 | enum { | 52 | enum { |
51 | BSG_F_BLOCK = 1, | 53 | BSG_F_BLOCK = 1, |
52 | BSG_F_WRITE_PERM = 2, | ||
53 | }; | 54 | }; |
54 | 55 | ||
55 | #define BSG_DEFAULT_CMDS 64 | 56 | #define BSG_DEFAULT_CMDS 64 |
@@ -173,7 +174,7 @@ unlock: | |||
173 | } | 174 | } |
174 | 175 | ||
175 | static int blk_fill_sgv4_hdr_rq(struct request_queue *q, struct request *rq, | 176 | static int blk_fill_sgv4_hdr_rq(struct request_queue *q, struct request *rq, |
176 | struct sg_io_v4 *hdr, int has_write_perm) | 177 | struct sg_io_v4 *hdr, struct bsg_device *bd) |
177 | { | 178 | { |
178 | if (hdr->request_len > BLK_MAX_CDB) { | 179 | if (hdr->request_len > BLK_MAX_CDB) { |
179 | rq->cmd = kzalloc(hdr->request_len, GFP_KERNEL); | 180 | rq->cmd = kzalloc(hdr->request_len, GFP_KERNEL); |
@@ -186,7 +187,8 @@ static int blk_fill_sgv4_hdr_rq(struct request_queue *q, struct request *rq, | |||
186 | return -EFAULT; | 187 | return -EFAULT; |
187 | 188 | ||
188 | if (hdr->subprotocol == BSG_SUB_PROTOCOL_SCSI_CMD) { | 189 | if (hdr->subprotocol == BSG_SUB_PROTOCOL_SCSI_CMD) { |
189 | if (blk_verify_command(rq->cmd, has_write_perm)) | 190 | if (blk_cmd_filter_verify_command(bd->cmd_filter, rq->cmd, |
191 | bd->f_mode)) | ||
190 | return -EPERM; | 192 | return -EPERM; |
191 | } else if (!capable(CAP_SYS_RAWIO)) | 193 | } else if (!capable(CAP_SYS_RAWIO)) |
192 | return -EPERM; | 194 | return -EPERM; |
@@ -264,8 +266,7 @@ bsg_map_hdr(struct bsg_device *bd, struct sg_io_v4 *hdr) | |||
264 | rq = blk_get_request(q, rw, GFP_KERNEL); | 266 | rq = blk_get_request(q, rw, GFP_KERNEL); |
265 | if (!rq) | 267 | if (!rq) |
266 | return ERR_PTR(-ENOMEM); | 268 | return ERR_PTR(-ENOMEM); |
267 | ret = blk_fill_sgv4_hdr_rq(q, rq, hdr, test_bit(BSG_F_WRITE_PERM, | 269 | ret = blk_fill_sgv4_hdr_rq(q, rq, hdr, bd); |
268 | &bd->flags)); | ||
269 | if (ret) | 270 | if (ret) |
270 | goto out; | 271 | goto out; |
271 | 272 | ||
@@ -567,12 +568,23 @@ static inline void bsg_set_block(struct bsg_device *bd, struct file *file) | |||
567 | set_bit(BSG_F_BLOCK, &bd->flags); | 568 | set_bit(BSG_F_BLOCK, &bd->flags); |
568 | } | 569 | } |
569 | 570 | ||
570 | static inline void bsg_set_write_perm(struct bsg_device *bd, struct file *file) | 571 | static void bsg_set_cmd_filter(struct bsg_device *bd, |
572 | struct file *file) | ||
571 | { | 573 | { |
572 | if (file->f_mode & FMODE_WRITE) | 574 | struct inode *inode; |
573 | set_bit(BSG_F_WRITE_PERM, &bd->flags); | 575 | struct gendisk *disk; |
574 | else | 576 | |
575 | clear_bit(BSG_F_WRITE_PERM, &bd->flags); | 577 | if (!file) |
578 | return; | ||
579 | |||
580 | inode = file->f_dentry->d_inode; | ||
581 | if (!inode) | ||
582 | return; | ||
583 | |||
584 | disk = inode->i_bdev->bd_disk; | ||
585 | |||
586 | bd->cmd_filter = &disk->cmd_filter; | ||
587 | bd->f_mode = &file->f_mode; | ||
576 | } | 588 | } |
577 | 589 | ||
578 | /* | 590 | /* |
@@ -596,6 +608,8 @@ bsg_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) | |||
596 | dprintk("%s: read %Zd bytes\n", bd->name, count); | 608 | dprintk("%s: read %Zd bytes\n", bd->name, count); |
597 | 609 | ||
598 | bsg_set_block(bd, file); | 610 | bsg_set_block(bd, file); |
611 | bsg_set_cmd_filter(bd, file); | ||
612 | |||
599 | bytes_read = 0; | 613 | bytes_read = 0; |
600 | ret = __bsg_read(buf, count, bd, NULL, &bytes_read); | 614 | ret = __bsg_read(buf, count, bd, NULL, &bytes_read); |
601 | *ppos = bytes_read; | 615 | *ppos = bytes_read; |
@@ -669,7 +683,7 @@ bsg_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) | |||
669 | dprintk("%s: write %Zd bytes\n", bd->name, count); | 683 | dprintk("%s: write %Zd bytes\n", bd->name, count); |
670 | 684 | ||
671 | bsg_set_block(bd, file); | 685 | bsg_set_block(bd, file); |
672 | bsg_set_write_perm(bd, file); | 686 | bsg_set_cmd_filter(bd, file); |
673 | 687 | ||
674 | bytes_written = 0; | 688 | bytes_written = 0; |
675 | ret = __bsg_write(bd, buf, count, &bytes_written); | 689 | ret = __bsg_write(bd, buf, count, &bytes_written); |
@@ -773,7 +787,9 @@ static struct bsg_device *bsg_add_device(struct inode *inode, | |||
773 | } | 787 | } |
774 | 788 | ||
775 | bd->queue = rq; | 789 | bd->queue = rq; |
790 | |||
776 | bsg_set_block(bd, file); | 791 | bsg_set_block(bd, file); |
792 | bsg_set_cmd_filter(bd, file); | ||
777 | 793 | ||
778 | atomic_set(&bd->ref_count, 1); | 794 | atomic_set(&bd->ref_count, 1); |
779 | mutex_lock(&bsg_mutex); | 795 | mutex_lock(&bsg_mutex); |