]>
Commit | Line | Data |
---|---|---|
457c8996 | 1 | // SPDX-License-Identifier: GPL-2.0-only |
1da177e4 LT |
2 | /* |
3 | * Changes: | |
4 | * Arnaldo Carvalho de Melo <acme@conectiva.com.br> 08/23/2000 | |
5 | * - get rid of some verify_areas and use __copy*user and __get/put_user | |
6 | * for the ones that remain | |
7 | */ | |
8 | #include <linux/module.h> | |
9 | #include <linux/blkdev.h> | |
10 | #include <linux/interrupt.h> | |
11 | #include <linux/errno.h> | |
12 | #include <linux/kernel.h> | |
13 | #include <linux/sched.h> | |
14 | #include <linux/mm.h> | |
15 | #include <linux/string.h> | |
7c0f6ba6 | 16 | #include <linux/uaccess.h> |
1da177e4 LT |
17 | |
18 | #include <scsi/scsi.h> | |
beb40487 | 19 | #include <scsi/scsi_cmnd.h> |
1da177e4 LT |
20 | #include <scsi/scsi_device.h> |
21 | #include <scsi/scsi_eh.h> | |
22 | #include <scsi/scsi_host.h> | |
23 | #include <scsi/scsi_ioctl.h> | |
1da177e4 LT |
24 | #include <scsi/sg.h> |
25 | #include <scsi/scsi_dbg.h> | |
26 | ||
27 | #include "scsi_logging.h" | |
28 | ||
29 | #define NORMAL_RETRIES 5 | |
30 | #define IOCTL_NORMAL_TIMEOUT (10 * HZ) | |
1da177e4 LT |
31 | |
32 | #define MAX_BUF PAGE_SIZE | |
33 | ||
32993523 CH |
34 | /** |
35 | * ioctl_probe -- return host identification | |
36 | * @host: host to identify | |
37 | * @buffer: userspace buffer for identification | |
38 | * | |
39 | * Return an identifying string at @buffer, if @buffer is non-NULL, filling | |
40 | * to the length stored at * (int *) @buffer. | |
1da177e4 | 41 | */ |
1da177e4 LT |
42 | static int ioctl_probe(struct Scsi_Host *host, void __user *buffer) |
43 | { | |
44 | unsigned int len, slen; | |
45 | const char *string; | |
1da177e4 | 46 | |
32993523 | 47 | if (buffer) { |
1da177e4 LT |
48 | if (get_user(len, (unsigned int __user *) buffer)) |
49 | return -EFAULT; | |
50 | ||
51 | if (host->hostt->info) | |
52 | string = host->hostt->info(host); | |
53 | else | |
54 | string = host->hostt->name; | |
55 | if (string) { | |
56 | slen = strlen(string); | |
57 | if (len > slen) | |
58 | len = slen + 1; | |
59 | if (copy_to_user(buffer, string, len)) | |
60 | return -EFAULT; | |
61 | } | |
62 | } | |
32993523 | 63 | return 1; |
1da177e4 LT |
64 | } |
65 | ||
66 | /* | |
67 | ||
68 | * The SCSI_IOCTL_SEND_COMMAND ioctl sends a command out to the SCSI host. | |
69 | * The IOCTL_NORMAL_TIMEOUT and NORMAL_RETRIES variables are used. | |
70 | * | |
71 | * dev is the SCSI device struct ptr, *(int *) arg is the length of the | |
72 | * input data, if any, not including the command string & counts, | |
73 | * *((int *)arg + 1) is the output buffer size in bytes. | |
74 | * | |
75 | * *(char *) ((int *) arg)[2] the actual command byte. | |
76 | * | |
77 | * Note that if more than MAX_BUF bytes are requested to be transferred, | |
78 | * the ioctl will fail with error EINVAL. | |
79 | * | |
80 | * This size *does not* include the initial lengths that were passed. | |
81 | * | |
82 | * The SCSI command is read from the memory location immediately after the | |
83 | * length words, and the input data is right after the command. The SCSI | |
84 | * routines know the command size based on the opcode decode. | |
85 | * | |
86 | * The output area is then filled in starting from the command byte. | |
87 | */ | |
88 | ||
89 | static int ioctl_internal_command(struct scsi_device *sdev, char *cmd, | |
90 | int timeout, int retries) | |
91 | { | |
1da177e4 LT |
92 | int result; |
93 | struct scsi_sense_hdr sshdr; | |
94 | ||
e5f73ce3 HR |
95 | SCSI_LOG_IOCTL(1, sdev_printk(KERN_INFO, sdev, |
96 | "Trying ioctl with scsi command %d\n", *cmd)); | |
1da177e4 | 97 | |
1cf72699 | 98 | result = scsi_execute_req(sdev, cmd, DMA_NONE, NULL, 0, |
f4f4e47e | 99 | &sshdr, timeout, retries, NULL); |
1da177e4 | 100 | |
e5f73ce3 HR |
101 | SCSI_LOG_IOCTL(2, sdev_printk(KERN_INFO, sdev, |
102 | "Ioctl returned 0x%x\n", result)); | |
1da177e4 | 103 | |
c65be1a6 JT |
104 | if (driver_byte(result) == DRIVER_SENSE && |
105 | scsi_sense_valid(&sshdr)) { | |
1da177e4 LT |
106 | switch (sshdr.sense_key) { |
107 | case ILLEGAL_REQUEST: | |
108 | if (cmd[0] == ALLOW_MEDIUM_REMOVAL) | |
109 | sdev->lockable = 0; | |
110 | else | |
e5f73ce3 HR |
111 | sdev_printk(KERN_INFO, sdev, |
112 | "ioctl_internal_command: " | |
113 | "ILLEGAL REQUEST " | |
114 | "asc=0x%x ascq=0x%x\n", | |
115 | sshdr.asc, sshdr.ascq); | |
1da177e4 LT |
116 | break; |
117 | case NOT_READY: /* This happens if there is no disc in drive */ | |
a75ad3c2 | 118 | if (sdev->removable) |
1da177e4 | 119 | break; |
3bf2ff67 | 120 | /* FALLTHROUGH */ |
1da177e4 LT |
121 | case UNIT_ATTENTION: |
122 | if (sdev->removable) { | |
123 | sdev->changed = 1; | |
1cf72699 | 124 | result = 0; /* This is no longer considered an error */ |
1da177e4 LT |
125 | break; |
126 | } | |
3bf2ff67 BVA |
127 | /* FALLTHROUGH -- for non-removable media */ |
128 | default: | |
9ccfc756 JB |
129 | sdev_printk(KERN_INFO, sdev, |
130 | "ioctl_internal_command return code = %x\n", | |
131 | result); | |
d811b848 | 132 | scsi_print_sense_hdr(sdev, NULL, &sshdr); |
1da177e4 LT |
133 | break; |
134 | } | |
135 | } | |
136 | ||
e5f73ce3 HR |
137 | SCSI_LOG_IOCTL(2, sdev_printk(KERN_INFO, sdev, |
138 | "IOCTL Releasing command\n")); | |
1da177e4 LT |
139 | return result; |
140 | } | |
141 | ||
142 | int scsi_set_medium_removal(struct scsi_device *sdev, char state) | |
143 | { | |
144 | char scsi_cmd[MAX_COMMAND_SIZE]; | |
145 | int ret; | |
146 | ||
147 | if (!sdev->removable || !sdev->lockable) | |
148 | return 0; | |
149 | ||
150 | scsi_cmd[0] = ALLOW_MEDIUM_REMOVAL; | |
151 | scsi_cmd[1] = 0; | |
152 | scsi_cmd[2] = 0; | |
153 | scsi_cmd[3] = 0; | |
154 | scsi_cmd[4] = state; | |
155 | scsi_cmd[5] = 0; | |
156 | ||
157 | ret = ioctl_internal_command(sdev, scsi_cmd, | |
158 | IOCTL_NORMAL_TIMEOUT, NORMAL_RETRIES); | |
159 | if (ret == 0) | |
160 | sdev->locked = (state == SCSI_REMOVAL_PREVENT); | |
161 | return ret; | |
162 | } | |
163 | EXPORT_SYMBOL(scsi_set_medium_removal); | |
164 | ||
1da177e4 LT |
165 | /* |
166 | * The scsi_ioctl_get_pci() function places into arg the value | |
167 | * pci_dev::slot_name (8 characters) for the PCI device (if any). | |
168 | * Returns: 0 on success | |
169 | * -ENXIO if there isn't a PCI device pointer | |
170 | * (could be because the SCSI driver hasn't been | |
171 | * updated yet, or because it isn't a SCSI | |
172 | * device) | |
173 | * any copy_to_user() error on failure there | |
174 | */ | |
175 | static int scsi_ioctl_get_pci(struct scsi_device *sdev, void __user *arg) | |
176 | { | |
177 | struct device *dev = scsi_get_device(sdev->host); | |
71610f55 | 178 | const char *name; |
1da177e4 LT |
179 | |
180 | if (!dev) | |
181 | return -ENXIO; | |
71610f55 KS |
182 | |
183 | name = dev_name(dev); | |
184 | ||
185 | /* compatibility with old ioctl which only returned | |
186 | * 20 characters */ | |
187 | return copy_to_user(arg, name, min(strlen(name), (size_t)20)) | |
188 | ? -EFAULT: 0; | |
1da177e4 LT |
189 | } |
190 | ||
191 | ||
7eafd137 | 192 | static int scsi_ioctl_common(struct scsi_device *sdev, int cmd, void __user *arg) |
1da177e4 LT |
193 | { |
194 | char scsi_cmd[MAX_COMMAND_SIZE]; | |
74a78ebd | 195 | struct scsi_sense_hdr sense_hdr; |
1da177e4 | 196 | |
1da177e4 LT |
197 | /* Check for deprecated ioctls ... all the ioctls which don't |
198 | * follow the new unique numbering scheme are deprecated */ | |
199 | switch (cmd) { | |
200 | case SCSI_IOCTL_SEND_COMMAND: | |
201 | case SCSI_IOCTL_TEST_UNIT_READY: | |
202 | case SCSI_IOCTL_BENCHMARK_COMMAND: | |
203 | case SCSI_IOCTL_SYNC: | |
204 | case SCSI_IOCTL_START_UNIT: | |
205 | case SCSI_IOCTL_STOP_UNIT: | |
206 | printk(KERN_WARNING "program %s is using a deprecated SCSI " | |
207 | "ioctl, please convert it to SG_IO\n", current->comm); | |
208 | break; | |
209 | default: | |
210 | break; | |
211 | } | |
212 | ||
213 | switch (cmd) { | |
214 | case SCSI_IOCTL_GET_IDLUN: | |
96d4f267 | 215 | if (!access_ok(arg, sizeof(struct scsi_idlun))) |
1da177e4 LT |
216 | return -EFAULT; |
217 | ||
218 | __put_user((sdev->id & 0xff) | |
219 | + ((sdev->lun & 0xff) << 8) | |
220 | + ((sdev->channel & 0xff) << 16) | |
221 | + ((sdev->host->host_no & 0xff) << 24), | |
222 | &((struct scsi_idlun __user *)arg)->dev_id); | |
223 | __put_user(sdev->host->unique_id, | |
224 | &((struct scsi_idlun __user *)arg)->host_unique_id); | |
225 | return 0; | |
226 | case SCSI_IOCTL_GET_BUS_NUMBER: | |
227 | return put_user(sdev->host->host_no, (int __user *)arg); | |
228 | case SCSI_IOCTL_PROBE_HOST: | |
229 | return ioctl_probe(sdev->host, arg); | |
230 | case SCSI_IOCTL_SEND_COMMAND: | |
231 | if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO)) | |
232 | return -EACCES; | |
e915e872 | 233 | return sg_scsi_ioctl(sdev->request_queue, NULL, 0, arg); |
1da177e4 LT |
234 | case SCSI_IOCTL_DOORLOCK: |
235 | return scsi_set_medium_removal(sdev, SCSI_REMOVAL_PREVENT); | |
236 | case SCSI_IOCTL_DOORUNLOCK: | |
237 | return scsi_set_medium_removal(sdev, SCSI_REMOVAL_ALLOW); | |
238 | case SCSI_IOCTL_TEST_UNIT_READY: | |
239 | return scsi_test_unit_ready(sdev, IOCTL_NORMAL_TIMEOUT, | |
74a78ebd | 240 | NORMAL_RETRIES, &sense_hdr); |
1da177e4 LT |
241 | case SCSI_IOCTL_START_UNIT: |
242 | scsi_cmd[0] = START_STOP; | |
243 | scsi_cmd[1] = 0; | |
244 | scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[5] = 0; | |
245 | scsi_cmd[4] = 1; | |
246 | return ioctl_internal_command(sdev, scsi_cmd, | |
247 | START_STOP_TIMEOUT, NORMAL_RETRIES); | |
248 | case SCSI_IOCTL_STOP_UNIT: | |
249 | scsi_cmd[0] = START_STOP; | |
250 | scsi_cmd[1] = 0; | |
251 | scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[5] = 0; | |
252 | scsi_cmd[4] = 0; | |
253 | return ioctl_internal_command(sdev, scsi_cmd, | |
254 | START_STOP_TIMEOUT, NORMAL_RETRIES); | |
255 | case SCSI_IOCTL_GET_PCI: | |
256 | return scsi_ioctl_get_pci(sdev, arg); | |
906d15fb CH |
257 | case SG_SCSI_RESET: |
258 | return scsi_ioctl_reset(sdev, arg); | |
1da177e4 | 259 | } |
7eafd137 AB |
260 | return -ENOIOCTLCMD; |
261 | } | |
262 | ||
263 | /** | |
264 | * scsi_ioctl - Dispatch ioctl to scsi device | |
265 | * @sdev: scsi device receiving ioctl | |
266 | * @cmd: which ioctl is it | |
267 | * @arg: data associated with ioctl | |
268 | * | |
269 | * Description: The scsi_ioctl() function differs from most ioctls in that it | |
270 | * does not take a major/minor number as the dev field. Rather, it takes | |
271 | * a pointer to a &struct scsi_device. | |
272 | */ | |
273 | int scsi_ioctl(struct scsi_device *sdev, int cmd, void __user *arg) | |
274 | { | |
275 | int ret = scsi_ioctl_common(sdev, cmd, arg); | |
276 | ||
277 | if (ret != -ENOIOCTLCMD) | |
278 | return ret; | |
279 | ||
280 | if (sdev->host->hostt->ioctl) | |
281 | return sdev->host->hostt->ioctl(sdev, cmd, arg); | |
282 | ||
1da177e4 LT |
283 | return -EINVAL; |
284 | } | |
285 | EXPORT_SYMBOL(scsi_ioctl); | |
286 | ||
7eafd137 AB |
287 | #ifdef CONFIG_COMPAT |
288 | int scsi_compat_ioctl(struct scsi_device *sdev, int cmd, void __user *arg) | |
289 | { | |
290 | int ret = scsi_ioctl_common(sdev, cmd, arg); | |
291 | ||
292 | if (ret != -ENOIOCTLCMD) | |
293 | return ret; | |
294 | ||
295 | if (sdev->host->hostt->compat_ioctl) | |
296 | return sdev->host->hostt->compat_ioctl(sdev, cmd, arg); | |
297 | ||
298 | return ret; | |
299 | } | |
300 | EXPORT_SYMBOL(scsi_compat_ioctl); | |
301 | #endif | |
302 | ||
906d15fb CH |
303 | /* |
304 | * We can process a reset even when a device isn't fully operable. | |
1da177e4 | 305 | */ |
906d15fb CH |
306 | int scsi_ioctl_block_when_processing_errors(struct scsi_device *sdev, int cmd, |
307 | bool ndelay) | |
1da177e4 | 308 | { |
906d15fb | 309 | if (cmd == SG_SCSI_RESET && ndelay) { |
939647ee | 310 | if (scsi_host_in_recovery(sdev->host)) |
e9afccc5 | 311 | return -EAGAIN; |
906d15fb CH |
312 | } else { |
313 | if (!scsi_block_when_processing_errors(sdev)) | |
314 | return -ENODEV; | |
1da177e4 | 315 | } |
906d15fb CH |
316 | |
317 | return 0; | |
1da177e4 | 318 | } |
906d15fb | 319 | EXPORT_SYMBOL_GPL(scsi_ioctl_block_when_processing_errors); |