1 /*
2 * Check decoding of ioctl SG_IO v3 commands.
3 *
4 * Copyright (c) 2017 Dmitry V. Levin <ldv@altlinux.org>
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30 #include "tests.h"
31
32 #ifdef HAVE_SCSI_SG_H
33
34 # include <inttypes.h>
35 # include <stdio.h>
36 # include <sys/ioctl.h>
37 # include <sys/uio.h>
38 # include <scsi/sg.h>
39
40 int
main(void)41 main(void)
42 {
43 ioctl(-1, SG_IO, 0);
44 printf("ioctl(-1, SG_IO, NULL) = -1 EBADF (%m)\n");
45
46 TAIL_ALLOC_OBJECT_CONST_PTR(struct sg_io_hdr, sg_io);
47 fill_memory(sg_io, sizeof(*sg_io));
48
49 const void *const efault = sg_io + 1;
50 ioctl(-1, SG_IO, efault);
51 printf("ioctl(-1, SG_IO, %p) = -1 EBADF (%m)\n", efault);
52
53 ioctl(-1, SG_IO, sg_io);
54 printf("ioctl(-1, SG_IO, [%u]) = -1 EBADF (%m)\n", sg_io->interface_id);
55
56 TAIL_ALLOC_OBJECT_CONST_PTR(unsigned int, piid);
57 *piid = (unsigned char) 'S';
58 ioctl(-1, SG_IO, piid);
59 printf("ioctl(-1, SG_IO, {interface_id='S', %p}) = -1 EBADF (%m)\n", piid + 1);
60
61 sg_io->interface_id = (unsigned char) 'S';
62 sg_io->dxfer_direction = -2;
63 sg_io->flags = -1U;
64 sg_io->info = -1U;
65 sg_io->dxferp = (void *) (unsigned long) 0xfacefeedfffffff1ULL;
66 sg_io->cmdp = (void *) (unsigned long) 0xfacefeedfffffff2ULL;
67 sg_io->sbp = (void *) (unsigned long) 0xfacefeedfffffff3ULL;
68
69 ioctl(-1, SG_IO, sg_io);
70 printf("ioctl(-1, SG_IO, {interface_id='S'"
71 ", dxfer_direction=SG_DXFER_TO_DEV"
72 ", cmd_len=%u"
73 ", cmdp=%p"
74 ", mx_sb_len=%u"
75 ", iovec_count=%u"
76 ", dxfer_len=%u"
77 ", timeout=%u"
78 ", flags=SG_FLAG_DIRECT_IO|SG_FLAG_UNUSED_LUN_INHIBIT"
79 "|SG_FLAG_MMAP_IO|SG_FLAG_NO_DXFER"
80 "|SG_FLAG_Q_AT_TAIL|SG_FLAG_Q_AT_HEAD|0xfffeffc8"
81 ", dxferp=%p"
82 ", status=%#x"
83 ", masked_status=%#x"
84 ", msg_status=%#x"
85 ", sb_len_wr=%u"
86 ", sbp=%p"
87 ", host_status=%#x"
88 ", driver_status=%#x"
89 ", resid=%d"
90 ", duration=%u"
91 ", info=SG_INFO_CHECK|SG_INFO_DIRECT_IO|SG_INFO_MIXED_IO|0xfffffff8"
92 "}) = -1 EBADF (%m)\n",
93 sg_io->cmd_len,
94 sg_io->cmdp,
95 sg_io->mx_sb_len,
96 sg_io->iovec_count,
97 sg_io->dxfer_len,
98 sg_io->timeout,
99 sg_io->dxferp,
100 sg_io->status,
101 sg_io->masked_status,
102 sg_io->msg_status,
103 sg_io->sb_len_wr,
104 sg_io->sbp,
105 sg_io->host_status,
106 sg_io->driver_status,
107 sg_io->resid,
108 sg_io->duration);
109
110 sg_io->dxfer_direction = -3;
111
112 ioctl(-1, SG_IO, sg_io);
113 printf("ioctl(-1, SG_IO, {interface_id='S'"
114 ", dxfer_direction=SG_DXFER_FROM_DEV"
115 ", cmd_len=%u"
116 ", cmdp=%p"
117 ", mx_sb_len=%u"
118 ", iovec_count=%u"
119 ", dxfer_len=%u"
120 ", timeout=%u"
121 ", flags=SG_FLAG_DIRECT_IO|SG_FLAG_UNUSED_LUN_INHIBIT"
122 "|SG_FLAG_MMAP_IO|SG_FLAG_NO_DXFER"
123 "|SG_FLAG_Q_AT_TAIL|SG_FLAG_Q_AT_HEAD|0xfffeffc8"
124 ", dxferp=%p"
125 ", status=%#x"
126 ", masked_status=%#x"
127 ", msg_status=%#x"
128 ", sb_len_wr=%u"
129 ", sbp=%p"
130 ", host_status=%#x"
131 ", driver_status=%#x"
132 ", resid=%d"
133 ", duration=%u"
134 ", info=SG_INFO_CHECK|SG_INFO_DIRECT_IO|SG_INFO_MIXED_IO|0xfffffff8"
135 "}) = -1 EBADF (%m)\n",
136 sg_io->cmd_len,
137 sg_io->cmdp,
138 sg_io->mx_sb_len,
139 sg_io->iovec_count,
140 sg_io->dxfer_len,
141 sg_io->timeout,
142 sg_io->dxferp,
143 sg_io->status,
144 sg_io->masked_status,
145 sg_io->msg_status,
146 sg_io->sb_len_wr,
147 sg_io->sbp,
148 sg_io->host_status,
149 sg_io->driver_status,
150 sg_io->resid,
151 sg_io->duration);
152
153 const struct iovec iov[] = {
154 {
155 .iov_base = (void *) efault - 2,
156 .iov_len = 2
157 }, {
158 .iov_base = (void *) efault - 3,
159 .iov_len = 4
160 }
161 };
162 struct iovec *const t_iov = tail_memdup(iov, sizeof(iov));
163
164 sg_io->flags = 0x24;
165 sg_io->info = 1;
166 sg_io->dxfer_direction = -2;
167
168 sg_io->iovec_count = ARRAY_SIZE(iov);
169 sg_io->dxfer_len = iov[0].iov_len + iov[1].iov_len - 1;
170 sg_io->dxferp = t_iov;
171
172 ioctl(-1, SG_IO, sg_io);
173 printf("ioctl(-1, SG_IO, {interface_id='S'"
174 ", dxfer_direction=SG_DXFER_TO_DEV"
175 ", cmd_len=%u"
176 ", cmdp=%p"
177 ", mx_sb_len=%u"
178 ", iovec_count=%u"
179 ", dxfer_len=%u"
180 ", timeout=%u"
181 ", flags=SG_FLAG_MMAP_IO|SG_FLAG_Q_AT_HEAD"
182 ", dxferp=[{iov_base=\"\\%o\\%o\", iov_len=%u}"
183 ", {iov_base=\"\\%o\\%o\\%o\", iov_len=%u}]"
184 ", status=%#x"
185 ", masked_status=%#x"
186 ", msg_status=%#x"
187 ", sb_len_wr=%u"
188 ", sbp=%p"
189 ", host_status=%#x"
190 ", driver_status=%#x"
191 ", resid=%d"
192 ", duration=%u"
193 ", info=SG_INFO_CHECK"
194 "}) = -1 EBADF (%m)\n",
195 sg_io->cmd_len,
196 sg_io->cmdp,
197 sg_io->mx_sb_len,
198 sg_io->iovec_count,
199 sg_io->dxfer_len,
200 sg_io->timeout,
201 *(unsigned char *) (iov[0].iov_base + 0),
202 *(unsigned char *) (iov[0].iov_base + 1),
203 (unsigned int) iov[0].iov_len,
204 *(unsigned char *) (iov[1].iov_base + 0),
205 *(unsigned char *) (iov[1].iov_base + 1),
206 *(unsigned char *) (iov[1].iov_base + 2),
207 (unsigned int) iov[1].iov_len,
208 sg_io->status,
209 sg_io->masked_status,
210 sg_io->msg_status,
211 sg_io->sb_len_wr,
212 sg_io->sbp,
213 sg_io->host_status,
214 sg_io->driver_status,
215 sg_io->resid,
216 sg_io->duration);
217
218 sg_io->flags = 0x11;
219 sg_io->dxfer_direction = -3;
220 sg_io->resid = sg_io->dxfer_len + 1;
221
222 ioctl(-1, SG_IO, sg_io);
223 printf("ioctl(-1, SG_IO, {interface_id='S'"
224 ", dxfer_direction=SG_DXFER_FROM_DEV"
225 ", cmd_len=%u"
226 ", cmdp=%p"
227 ", mx_sb_len=%u"
228 ", iovec_count=%u"
229 ", dxfer_len=%u"
230 ", timeout=%u"
231 ", flags=SG_FLAG_DIRECT_IO|SG_FLAG_Q_AT_TAIL"
232 ", dxferp=[{iov_base=\"\\%o\\%o\", iov_len=%u}"
233 ", {iov_base=\"\\%o\\%o\\%o\", iov_len=%u}]"
234 ", status=%#x"
235 ", masked_status=%#x"
236 ", msg_status=%#x"
237 ", sb_len_wr=%u"
238 ", sbp=%p"
239 ", host_status=%#x"
240 ", driver_status=%#x"
241 ", resid=%d"
242 ", duration=%u"
243 ", info=SG_INFO_CHECK"
244 "}) = -1 EBADF (%m)\n",
245 sg_io->cmd_len,
246 sg_io->cmdp,
247 sg_io->mx_sb_len,
248 sg_io->iovec_count,
249 sg_io->dxfer_len,
250 sg_io->timeout,
251 *(unsigned char *) (iov[0].iov_base + 0),
252 *(unsigned char *) (iov[0].iov_base + 1),
253 (unsigned int) iov[0].iov_len,
254 *(unsigned char *) (iov[1].iov_base + 0),
255 *(unsigned char *) (iov[1].iov_base + 1),
256 *(unsigned char *) (iov[1].iov_base + 2),
257 (unsigned int) iov[1].iov_len,
258 sg_io->status,
259 sg_io->masked_status,
260 sg_io->msg_status,
261 sg_io->sb_len_wr,
262 sg_io->sbp,
263 sg_io->host_status,
264 sg_io->driver_status,
265 sg_io->resid,
266 sg_io->duration);
267
268 sg_io->flags = 0x10000;
269 sg_io->info = 0xdeadbeef;
270 sg_io->iovec_count = 0;
271 sg_io->dxfer_len = 5;
272 sg_io->resid = 1;
273 sg_io->dxferp = (void *) efault - (sg_io->dxfer_len - sg_io->resid);
274
275 ioctl(-1, SG_IO, sg_io);
276 printf("ioctl(-1, SG_IO, {interface_id='S'"
277 ", dxfer_direction=SG_DXFER_FROM_DEV"
278 ", cmd_len=%u"
279 ", cmdp=%p"
280 ", mx_sb_len=%u"
281 ", iovec_count=%u"
282 ", dxfer_len=%u"
283 ", timeout=%u"
284 ", flags=SG_FLAG_NO_DXFER"
285 ", dxferp=\"\\x%x\\x%x\\x%x\\x%x\""
286 ", status=%#x"
287 ", masked_status=%#x"
288 ", msg_status=%#x"
289 ", sb_len_wr=%u"
290 ", sbp=%p"
291 ", host_status=%#x"
292 ", driver_status=%#x"
293 ", resid=%d"
294 ", duration=%u"
295 ", info=SG_INFO_CHECK|SG_INFO_DIRECT_IO|SG_INFO_MIXED_IO|0xdeadbee8"
296 "}) = -1 EBADF (%m)\n",
297 sg_io->cmd_len,
298 sg_io->cmdp,
299 sg_io->mx_sb_len,
300 sg_io->iovec_count,
301 sg_io->dxfer_len,
302 sg_io->timeout,
303 *(unsigned char *) (sg_io->dxferp + 0),
304 *(unsigned char *) (sg_io->dxferp + 1),
305 *(unsigned char *) (sg_io->dxferp + 2),
306 *(unsigned char *) (sg_io->dxferp + 3),
307 sg_io->status,
308 sg_io->masked_status,
309 sg_io->msg_status,
310 sg_io->sb_len_wr,
311 sg_io->sbp,
312 sg_io->host_status,
313 sg_io->driver_status,
314 sg_io->resid,
315 sg_io->duration);
316
317 sg_io->flags = 2;
318 sg_io->dxfer_direction = -4;
319 sg_io->dxfer_len = 3;
320 sg_io->resid = 1;
321 sg_io->dxferp = (void *) efault - sg_io->dxfer_len;
322
323 ioctl(-1, SG_IO, sg_io);
324 printf("ioctl(-1, SG_IO, {interface_id='S'"
325 ", dxfer_direction=SG_DXFER_TO_FROM_DEV"
326 ", cmd_len=%u"
327 ", cmdp=%p"
328 ", mx_sb_len=%u"
329 ", iovec_count=%u"
330 ", dxfer_len=%u"
331 ", timeout=%u"
332 ", flags=SG_FLAG_UNUSED_LUN_INHIBIT"
333 ", dxferp=\"\\x%x\\x%x\\x%x\" => dxferp=\"\\x%x\\x%x\""
334 ", status=%#x"
335 ", masked_status=%#x"
336 ", msg_status=%#x"
337 ", sb_len_wr=%u"
338 ", sbp=%p"
339 ", host_status=%#x"
340 ", driver_status=%#x"
341 ", resid=%d"
342 ", duration=%u"
343 ", info=SG_INFO_CHECK|SG_INFO_DIRECT_IO|SG_INFO_MIXED_IO|0xdeadbee8"
344 "}) = -1 EBADF (%m)\n",
345 sg_io->cmd_len,
346 sg_io->cmdp,
347 sg_io->mx_sb_len,
348 sg_io->iovec_count,
349 sg_io->dxfer_len,
350 sg_io->timeout,
351 *(unsigned char *) (sg_io->dxferp + 0),
352 *(unsigned char *) (sg_io->dxferp + 1),
353 *(unsigned char *) (sg_io->dxferp + 2),
354 *(unsigned char *) (sg_io->dxferp + 0),
355 *(unsigned char *) (sg_io->dxferp + 1),
356 sg_io->status,
357 sg_io->masked_status,
358 sg_io->msg_status,
359 sg_io->sb_len_wr,
360 sg_io->sbp,
361 sg_io->host_status,
362 sg_io->driver_status,
363 sg_io->resid,
364 sg_io->duration);
365
366 sg_io->flags = 0;
367 sg_io->resid = sg_io->dxfer_len;
368
369 ioctl(-1, SG_IO, sg_io);
370 printf("ioctl(-1, SG_IO, {interface_id='S'"
371 ", dxfer_direction=SG_DXFER_TO_FROM_DEV"
372 ", cmd_len=%u"
373 ", cmdp=%p"
374 ", mx_sb_len=%u"
375 ", iovec_count=%u"
376 ", dxfer_len=%u"
377 ", timeout=%u"
378 ", flags=0"
379 ", dxferp=\"\\x%x\\x%x\\x%x\""
380 ", status=%#x"
381 ", masked_status=%#x"
382 ", msg_status=%#x"
383 ", sb_len_wr=%u"
384 ", sbp=%p"
385 ", host_status=%#x"
386 ", driver_status=%#x"
387 ", resid=%d"
388 ", duration=%u"
389 ", info=SG_INFO_CHECK|SG_INFO_DIRECT_IO|SG_INFO_MIXED_IO|0xdeadbee8"
390 "}) = -1 EBADF (%m)\n",
391 sg_io->cmd_len,
392 sg_io->cmdp,
393 sg_io->mx_sb_len,
394 sg_io->iovec_count,
395 sg_io->dxfer_len,
396 sg_io->timeout,
397 *(unsigned char *) (sg_io->dxferp + 0),
398 *(unsigned char *) (sg_io->dxferp + 1),
399 *(unsigned char *) (sg_io->dxferp + 2),
400 sg_io->status,
401 sg_io->masked_status,
402 sg_io->msg_status,
403 sg_io->sb_len_wr,
404 sg_io->sbp,
405 sg_io->host_status,
406 sg_io->driver_status,
407 sg_io->resid,
408 sg_io->duration);
409
410 puts("+++ exited with 0 +++");
411 return 0;
412 }
413
414 #else
415
416 SKIP_MAIN_UNDEFINED("HAVE_SCSI_SG_H")
417
418 #endif
419