diff options
author | FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> | 2008-08-16 01:10:05 -0400 |
---|---|---|
committer | Jens Axboe <jens.axboe@oracle.com> | 2008-08-27 03:50:19 -0400 |
commit | abf5439370491dd6fbb4fe1a7939680d2a9bc9d4 (patch) | |
tree | aa3630557fe4a4bc6313617f5770af30eec68515 /block/scsi_ioctl.c | |
parent | 1941246dd98089dd637f44d3bd4f6cc1c61aa9e4 (diff) |
block: move cmdfilter from gendisk to request_queue
cmd_filter works only for the block layer SG_IO with SCSI block
devices. It breaks scsi/sg.c, bsg, and the block layer SG_IO with SCSI
character devices (such as st). We hit a kernel crash with them.
The problem is that cmd_filter code accesses to gendisk (having struct
blk_scsi_cmd_filter) via inode->i_bdev->bd_disk. It works for only
SCSI block device files. With character device files, inode->i_bdev
leads you to struct cdev. inode->i_bdev->bd_disk->blk_scsi_cmd_filter
isn't safe.
SCSI ULDs don't expose gendisk; they keep it private. bsg needs to be
independent on any protocols. We shouldn't change ULDs to expose their
gendisk.
This patch moves struct blk_scsi_cmd_filter from gendisk to
request_queue, a common object, which eveyone can access to.
The user interface doesn't change; users can change the filters via
/sys/block/. gendisk has a pointer to request_queue so the cmd_filter
code accesses to struct blk_scsi_cmd_filter.
Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
Diffstat (limited to 'block/scsi_ioctl.c')
-rw-r--r-- | block/scsi_ioctl.c | 94 |
1 files changed, 91 insertions, 3 deletions
diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c index 12a5182173f6..d01ef5ee427e 100644 --- a/block/scsi_ioctl.c +++ b/block/scsi_ioctl.c | |||
@@ -105,12 +105,96 @@ static int sg_emulated_host(struct request_queue *q, int __user *p) | |||
105 | return put_user(1, p); | 105 | return put_user(1, p); |
106 | } | 106 | } |
107 | 107 | ||
108 | void blk_set_cmd_filter_defaults(struct blk_scsi_cmd_filter *filter) | ||
109 | { | ||
110 | /* Basic read-only commands */ | ||
111 | __set_bit(TEST_UNIT_READY, filter->read_ok); | ||
112 | __set_bit(REQUEST_SENSE, filter->read_ok); | ||
113 | __set_bit(READ_6, filter->read_ok); | ||
114 | __set_bit(READ_10, filter->read_ok); | ||
115 | __set_bit(READ_12, filter->read_ok); | ||
116 | __set_bit(READ_16, filter->read_ok); | ||
117 | __set_bit(READ_BUFFER, filter->read_ok); | ||
118 | __set_bit(READ_DEFECT_DATA, filter->read_ok); | ||
119 | __set_bit(READ_CAPACITY, filter->read_ok); | ||
120 | __set_bit(READ_LONG, filter->read_ok); | ||
121 | __set_bit(INQUIRY, filter->read_ok); | ||
122 | __set_bit(MODE_SENSE, filter->read_ok); | ||
123 | __set_bit(MODE_SENSE_10, filter->read_ok); | ||
124 | __set_bit(LOG_SENSE, filter->read_ok); | ||
125 | __set_bit(START_STOP, filter->read_ok); | ||
126 | __set_bit(GPCMD_VERIFY_10, filter->read_ok); | ||
127 | __set_bit(VERIFY_16, filter->read_ok); | ||
128 | __set_bit(REPORT_LUNS, filter->read_ok); | ||
129 | __set_bit(SERVICE_ACTION_IN, filter->read_ok); | ||
130 | __set_bit(RECEIVE_DIAGNOSTIC, filter->read_ok); | ||
131 | __set_bit(MAINTENANCE_IN, filter->read_ok); | ||
132 | __set_bit(GPCMD_READ_BUFFER_CAPACITY, filter->read_ok); | ||
133 | |||
134 | /* Audio CD commands */ | ||
135 | __set_bit(GPCMD_PLAY_CD, filter->read_ok); | ||
136 | __set_bit(GPCMD_PLAY_AUDIO_10, filter->read_ok); | ||
137 | __set_bit(GPCMD_PLAY_AUDIO_MSF, filter->read_ok); | ||
138 | __set_bit(GPCMD_PLAY_AUDIO_TI, filter->read_ok); | ||
139 | __set_bit(GPCMD_PAUSE_RESUME, filter->read_ok); | ||
140 | |||
141 | /* CD/DVD data reading */ | ||
142 | __set_bit(GPCMD_READ_CD, filter->read_ok); | ||
143 | __set_bit(GPCMD_READ_CD_MSF, filter->read_ok); | ||
144 | __set_bit(GPCMD_READ_DISC_INFO, filter->read_ok); | ||
145 | __set_bit(GPCMD_READ_CDVD_CAPACITY, filter->read_ok); | ||
146 | __set_bit(GPCMD_READ_DVD_STRUCTURE, filter->read_ok); | ||
147 | __set_bit(GPCMD_READ_HEADER, filter->read_ok); | ||
148 | __set_bit(GPCMD_READ_TRACK_RZONE_INFO, filter->read_ok); | ||
149 | __set_bit(GPCMD_READ_SUBCHANNEL, filter->read_ok); | ||
150 | __set_bit(GPCMD_READ_TOC_PMA_ATIP, filter->read_ok); | ||
151 | __set_bit(GPCMD_REPORT_KEY, filter->read_ok); | ||
152 | __set_bit(GPCMD_SCAN, filter->read_ok); | ||
153 | __set_bit(GPCMD_GET_CONFIGURATION, filter->read_ok); | ||
154 | __set_bit(GPCMD_READ_FORMAT_CAPACITIES, filter->read_ok); | ||
155 | __set_bit(GPCMD_GET_EVENT_STATUS_NOTIFICATION, filter->read_ok); | ||
156 | __set_bit(GPCMD_GET_PERFORMANCE, filter->read_ok); | ||
157 | __set_bit(GPCMD_SEEK, filter->read_ok); | ||
158 | __set_bit(GPCMD_STOP_PLAY_SCAN, filter->read_ok); | ||
159 | |||
160 | /* Basic writing commands */ | ||
161 | __set_bit(WRITE_6, filter->write_ok); | ||
162 | __set_bit(WRITE_10, filter->write_ok); | ||
163 | __set_bit(WRITE_VERIFY, filter->write_ok); | ||
164 | __set_bit(WRITE_12, filter->write_ok); | ||
165 | __set_bit(WRITE_VERIFY_12, filter->write_ok); | ||
166 | __set_bit(WRITE_16, filter->write_ok); | ||
167 | __set_bit(WRITE_LONG, filter->write_ok); | ||
168 | __set_bit(WRITE_LONG_2, filter->write_ok); | ||
169 | __set_bit(ERASE, filter->write_ok); | ||
170 | __set_bit(GPCMD_MODE_SELECT_10, filter->write_ok); | ||
171 | __set_bit(MODE_SELECT, filter->write_ok); | ||
172 | __set_bit(LOG_SELECT, filter->write_ok); | ||
173 | __set_bit(GPCMD_BLANK, filter->write_ok); | ||
174 | __set_bit(GPCMD_CLOSE_TRACK, filter->write_ok); | ||
175 | __set_bit(GPCMD_FLUSH_CACHE, filter->write_ok); | ||
176 | __set_bit(GPCMD_FORMAT_UNIT, filter->write_ok); | ||
177 | __set_bit(GPCMD_REPAIR_RZONE_TRACK, filter->write_ok); | ||
178 | __set_bit(GPCMD_RESERVE_RZONE_TRACK, filter->write_ok); | ||
179 | __set_bit(GPCMD_SEND_DVD_STRUCTURE, filter->write_ok); | ||
180 | __set_bit(GPCMD_SEND_EVENT, filter->write_ok); | ||
181 | __set_bit(GPCMD_SEND_KEY, filter->write_ok); | ||
182 | __set_bit(GPCMD_SEND_OPC, filter->write_ok); | ||
183 | __set_bit(GPCMD_SEND_CUE_SHEET, filter->write_ok); | ||
184 | __set_bit(GPCMD_SET_SPEED, filter->write_ok); | ||
185 | __set_bit(GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL, filter->write_ok); | ||
186 | __set_bit(GPCMD_LOAD_UNLOAD, filter->write_ok); | ||
187 | __set_bit(GPCMD_SET_STREAMING, filter->write_ok); | ||
188 | } | ||
189 | EXPORT_SYMBOL_GPL(blk_set_cmd_filter_defaults); | ||
190 | |||
108 | static int blk_fill_sghdr_rq(struct request_queue *q, struct request *rq, | 191 | static int blk_fill_sghdr_rq(struct request_queue *q, struct request *rq, |
109 | struct sg_io_hdr *hdr, struct file *file) | 192 | struct sg_io_hdr *hdr, struct file *file) |
110 | { | 193 | { |
111 | if (copy_from_user(rq->cmd, hdr->cmdp, hdr->cmd_len)) | 194 | if (copy_from_user(rq->cmd, hdr->cmdp, hdr->cmd_len)) |
112 | return -EFAULT; | 195 | return -EFAULT; |
113 | if (blk_verify_command(file, rq->cmd)) | 196 | if (blk_verify_command(&q->cmd_filter, rq->cmd, |
197 | file->f_mode & FMODE_WRITE)) | ||
114 | return -EPERM; | 198 | return -EPERM; |
115 | 199 | ||
116 | /* | 200 | /* |
@@ -298,7 +382,7 @@ int sg_scsi_ioctl(struct file *file, struct request_queue *q, | |||
298 | struct gendisk *disk, struct scsi_ioctl_command __user *sic) | 382 | struct gendisk *disk, struct scsi_ioctl_command __user *sic) |
299 | { | 383 | { |
300 | struct request *rq; | 384 | struct request *rq; |
301 | int err; | 385 | int err, write_perm = 0; |
302 | unsigned int in_len, out_len, bytes, opcode, cmdlen; | 386 | unsigned int in_len, out_len, bytes, opcode, cmdlen; |
303 | char *buffer = NULL, sense[SCSI_SENSE_BUFFERSIZE]; | 387 | char *buffer = NULL, sense[SCSI_SENSE_BUFFERSIZE]; |
304 | 388 | ||
@@ -340,7 +424,11 @@ int sg_scsi_ioctl(struct file *file, struct request_queue *q, | |||
340 | if (in_len && copy_from_user(buffer, sic->data + cmdlen, in_len)) | 424 | if (in_len && copy_from_user(buffer, sic->data + cmdlen, in_len)) |
341 | goto error; | 425 | goto error; |
342 | 426 | ||
343 | err = blk_verify_command(file, rq->cmd); | 427 | /* scsi_ioctl passes NULL */ |
428 | if (file && (file->f_mode & FMODE_WRITE)) | ||
429 | write_perm = 1; | ||
430 | |||
431 | err = blk_verify_command(&q->cmd_filter, rq->cmd, write_perm); | ||
344 | if (err) | 432 | if (err) |
345 | goto error; | 433 | goto error; |
346 | 434 | ||