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