diff options
Diffstat (limited to 'block/scsi_ioctl.c')
-rw-r--r-- | block/scsi_ioctl.c | 121 |
1 files changed, 5 insertions, 116 deletions
diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c index 78199c08ec92..c5b9bcfc0a6d 100644 --- a/block/scsi_ioctl.c +++ b/block/scsi_ioctl.c | |||
@@ -105,120 +105,12 @@ 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 | #define CMD_READ_SAFE 0x01 | ||
109 | #define CMD_WRITE_SAFE 0x02 | ||
110 | #define CMD_WARNED 0x04 | ||
111 | #define safe_for_read(cmd) [cmd] = CMD_READ_SAFE | ||
112 | #define safe_for_write(cmd) [cmd] = CMD_WRITE_SAFE | ||
113 | |||
114 | int blk_verify_command(unsigned char *cmd, int has_write_perm) | ||
115 | { | ||
116 | static unsigned char cmd_type[256] = { | ||
117 | |||
118 | /* Basic read-only commands */ | ||
119 | safe_for_read(TEST_UNIT_READY), | ||
120 | safe_for_read(REQUEST_SENSE), | ||
121 | safe_for_read(READ_6), | ||
122 | safe_for_read(READ_10), | ||
123 | safe_for_read(READ_12), | ||
124 | safe_for_read(READ_16), | ||
125 | safe_for_read(READ_BUFFER), | ||
126 | safe_for_read(READ_DEFECT_DATA), | ||
127 | safe_for_read(READ_LONG), | ||
128 | safe_for_read(INQUIRY), | ||
129 | safe_for_read(MODE_SENSE), | ||
130 | safe_for_read(MODE_SENSE_10), | ||
131 | safe_for_read(LOG_SENSE), | ||
132 | safe_for_read(START_STOP), | ||
133 | safe_for_read(GPCMD_VERIFY_10), | ||
134 | safe_for_read(VERIFY_16), | ||
135 | |||
136 | /* Audio CD commands */ | ||
137 | safe_for_read(GPCMD_PLAY_CD), | ||
138 | safe_for_read(GPCMD_PLAY_AUDIO_10), | ||
139 | safe_for_read(GPCMD_PLAY_AUDIO_MSF), | ||
140 | safe_for_read(GPCMD_PLAY_AUDIO_TI), | ||
141 | safe_for_read(GPCMD_PAUSE_RESUME), | ||
142 | |||
143 | /* CD/DVD data reading */ | ||
144 | safe_for_read(GPCMD_READ_BUFFER_CAPACITY), | ||
145 | safe_for_read(GPCMD_READ_CD), | ||
146 | safe_for_read(GPCMD_READ_CD_MSF), | ||
147 | safe_for_read(GPCMD_READ_DISC_INFO), | ||
148 | safe_for_read(GPCMD_READ_CDVD_CAPACITY), | ||
149 | safe_for_read(GPCMD_READ_DVD_STRUCTURE), | ||
150 | safe_for_read(GPCMD_READ_HEADER), | ||
151 | safe_for_read(GPCMD_READ_TRACK_RZONE_INFO), | ||
152 | safe_for_read(GPCMD_READ_SUBCHANNEL), | ||
153 | safe_for_read(GPCMD_READ_TOC_PMA_ATIP), | ||
154 | safe_for_read(GPCMD_REPORT_KEY), | ||
155 | safe_for_read(GPCMD_SCAN), | ||
156 | safe_for_read(GPCMD_GET_CONFIGURATION), | ||
157 | safe_for_read(GPCMD_READ_FORMAT_CAPACITIES), | ||
158 | safe_for_read(GPCMD_GET_EVENT_STATUS_NOTIFICATION), | ||
159 | safe_for_read(GPCMD_GET_PERFORMANCE), | ||
160 | safe_for_read(GPCMD_SEEK), | ||
161 | safe_for_read(GPCMD_STOP_PLAY_SCAN), | ||
162 | |||
163 | /* Basic writing commands */ | ||
164 | safe_for_write(WRITE_6), | ||
165 | safe_for_write(WRITE_10), | ||
166 | safe_for_write(WRITE_VERIFY), | ||
167 | safe_for_write(WRITE_12), | ||
168 | safe_for_write(WRITE_VERIFY_12), | ||
169 | safe_for_write(WRITE_16), | ||
170 | safe_for_write(WRITE_LONG), | ||
171 | safe_for_write(WRITE_LONG_2), | ||
172 | safe_for_write(ERASE), | ||
173 | safe_for_write(GPCMD_MODE_SELECT_10), | ||
174 | safe_for_write(MODE_SELECT), | ||
175 | safe_for_write(LOG_SELECT), | ||
176 | safe_for_write(GPCMD_BLANK), | ||
177 | safe_for_write(GPCMD_CLOSE_TRACK), | ||
178 | safe_for_write(GPCMD_FLUSH_CACHE), | ||
179 | safe_for_write(GPCMD_FORMAT_UNIT), | ||
180 | safe_for_write(GPCMD_REPAIR_RZONE_TRACK), | ||
181 | safe_for_write(GPCMD_RESERVE_RZONE_TRACK), | ||
182 | safe_for_write(GPCMD_SEND_DVD_STRUCTURE), | ||
183 | safe_for_write(GPCMD_SEND_EVENT), | ||
184 | safe_for_write(GPCMD_SEND_KEY), | ||
185 | safe_for_write(GPCMD_SEND_OPC), | ||
186 | safe_for_write(GPCMD_SEND_CUE_SHEET), | ||
187 | safe_for_write(GPCMD_SET_SPEED), | ||
188 | safe_for_write(GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL), | ||
189 | safe_for_write(GPCMD_LOAD_UNLOAD), | ||
190 | safe_for_write(GPCMD_SET_STREAMING), | ||
191 | }; | ||
192 | unsigned char type = cmd_type[cmd[0]]; | ||
193 | |||
194 | /* Anybody who can open the device can do a read-safe command */ | ||
195 | if (type & CMD_READ_SAFE) | ||
196 | return 0; | ||
197 | |||
198 | /* Write-safe commands just require a writable open.. */ | ||
199 | if ((type & CMD_WRITE_SAFE) && has_write_perm) | ||
200 | return 0; | ||
201 | |||
202 | /* And root can do any command.. */ | ||
203 | if (capable(CAP_SYS_RAWIO)) | ||
204 | return 0; | ||
205 | |||
206 | if (!type) { | ||
207 | cmd_type[cmd[0]] = CMD_WARNED; | ||
208 | printk(KERN_WARNING "scsi: unknown opcode 0x%02x\n", cmd[0]); | ||
209 | } | ||
210 | |||
211 | /* Otherwise fail it with an "Operation not permitted" */ | ||
212 | return -EPERM; | ||
213 | } | ||
214 | EXPORT_SYMBOL_GPL(blk_verify_command); | ||
215 | |||
216 | static int blk_fill_sghdr_rq(struct request_queue *q, struct request *rq, | 108 | static int blk_fill_sghdr_rq(struct request_queue *q, struct request *rq, |
217 | struct sg_io_hdr *hdr, int has_write_perm) | 109 | struct sg_io_hdr *hdr, struct file *file) |
218 | { | 110 | { |
219 | if (copy_from_user(rq->cmd, hdr->cmdp, hdr->cmd_len)) | 111 | if (copy_from_user(rq->cmd, hdr->cmdp, hdr->cmd_len)) |
220 | return -EFAULT; | 112 | return -EFAULT; |
221 | if (blk_verify_command(rq->cmd, has_write_perm)) | 113 | if (blk_verify_command(file, rq->cmd)) |
222 | return -EPERM; | 114 | return -EPERM; |
223 | 115 | ||
224 | /* | 116 | /* |
@@ -287,7 +179,7 @@ static int sg_io(struct file *file, struct request_queue *q, | |||
287 | struct gendisk *bd_disk, struct sg_io_hdr *hdr) | 179 | struct gendisk *bd_disk, struct sg_io_hdr *hdr) |
288 | { | 180 | { |
289 | unsigned long start_time; | 181 | unsigned long start_time; |
290 | int writing = 0, ret = 0, has_write_perm = 0; | 182 | int writing = 0, ret = 0; |
291 | struct request *rq; | 183 | struct request *rq; |
292 | char sense[SCSI_SENSE_BUFFERSIZE]; | 184 | char sense[SCSI_SENSE_BUFFERSIZE]; |
293 | struct bio *bio; | 185 | struct bio *bio; |
@@ -316,10 +208,7 @@ static int sg_io(struct file *file, struct request_queue *q, | |||
316 | if (!rq) | 208 | if (!rq) |
317 | return -ENOMEM; | 209 | return -ENOMEM; |
318 | 210 | ||
319 | if (file) | 211 | if (blk_fill_sghdr_rq(q, rq, hdr, file)) { |
320 | has_write_perm = file->f_mode & FMODE_WRITE; | ||
321 | |||
322 | if (blk_fill_sghdr_rq(q, rq, hdr, has_write_perm)) { | ||
323 | blk_put_request(rq); | 212 | blk_put_request(rq); |
324 | return -EFAULT; | 213 | return -EFAULT; |
325 | } | 214 | } |
@@ -451,7 +340,7 @@ int sg_scsi_ioctl(struct file *file, struct request_queue *q, | |||
451 | if (in_len && copy_from_user(buffer, sic->data + cmdlen, in_len)) | 340 | if (in_len && copy_from_user(buffer, sic->data + cmdlen, in_len)) |
452 | goto error; | 341 | goto error; |
453 | 342 | ||
454 | err = blk_verify_command(rq->cmd, file->f_mode & FMODE_WRITE); | 343 | err = blk_verify_command(file, rq->cmd); |
455 | if (err) | 344 | if (err) |
456 | goto error; | 345 | goto error; |
457 | 346 | ||