1 /*
2 * Check decoding of ioctl SG_IO v3 commands.
3 *
4 * Copyright (c) 2017-2021 Dmitry V. Levin <ldv@strace.io>
5 * All rights reserved.
6 *
7 * SPDX-License-Identifier: GPL-2.0-or-later
8 */
9
10 #include "tests.h"
11
12 #ifdef HAVE_SCSI_SG_H
13
14 # include <inttypes.h>
15 # include <stdio.h>
16 # include <sys/ioctl.h>
17 # include <sys/uio.h>
18 # include <scsi/sg.h>
19
20 int
21 main(void)
22 {
23 ioctl(-1, SG_IO, 0);
24 printf("ioctl(-1, SG_IO, NULL) = -1 EBADF (%m)\n");
25
26 TAIL_ALLOC_OBJECT_CONST_PTR(struct sg_io_hdr, sg_io);
27 fill_memory(sg_io, sizeof(*sg_io));
28
29 const void *const efault = sg_io + 1;
30 ioctl(-1, SG_IO, efault);
31 printf("ioctl(-1, SG_IO, %p) = -1 EBADF (%m)\n", efault);
32
33 ioctl(-1, SG_IO, sg_io);
34 printf("ioctl(-1, SG_IO, [%u]) = -1 EBADF (%m)\n", sg_io->interface_id);
35
36 TAIL_ALLOC_OBJECT_CONST_PTR(unsigned int, piid);
37 *piid = (unsigned char) 'S';
38 ioctl(-1, SG_IO, piid);
39 printf("ioctl(-1, SG_IO, {interface_id='S', %p}) = -1 EBADF (%m)\n", piid + 1);
40
41 sg_io->interface_id = (unsigned char) 'S';
42 sg_io->dxfer_direction = -2;
43 sg_io->flags = -1U;
44 sg_io->info = -1U;
45 sg_io->dxferp = (void *) (unsigned long) 0xfacefeedfffffff1ULL;
46 sg_io->cmdp = (void *) (unsigned long) 0xfacefeedfffffff2ULL;
47 sg_io->sbp = (void *) (unsigned long) 0xfacefeedfffffff3ULL;
48
49 ioctl(-1, SG_IO, sg_io);
50 printf("ioctl(-1, SG_IO, {interface_id='S'"
51 ", dxfer_direction=SG_DXFER_TO_DEV"
52 ", cmd_len=%u"
53 ", cmdp=%p"
54 ", mx_sb_len=%u"
55 ", iovec_count=%u"
56 ", dxfer_len=%u"
57 ", timeout=%u"
58 ", flags=SG_FLAG_DIRECT_IO|SG_FLAG_UNUSED_LUN_INHIBIT"
59 "|SG_FLAG_MMAP_IO|SG_FLAG_NO_DXFER"
60 "|SG_FLAG_Q_AT_TAIL|SG_FLAG_Q_AT_HEAD|0xfffeffc8"
61 ", dxferp=%p"
62 ", status=%#x"
63 ", masked_status=%#x"
64 ", msg_status=%#x"
65 ", sb_len_wr=%u"
66 ", sbp=%p"
67 ", host_status=%#x"
68 ", driver_status=%#x"
69 ", resid=%d"
70 ", duration=%u"
71 ", info=SG_INFO_CHECK|SG_INFO_DIRECT_IO|SG_INFO_MIXED_IO|0xfffffff8"
72 "}) = -1 EBADF (%m)\n",
73 sg_io->cmd_len,
74 sg_io->cmdp,
75 sg_io->mx_sb_len,
76 sg_io->iovec_count,
77 sg_io->dxfer_len,
78 sg_io->timeout,
79 sg_io->dxferp,
80 sg_io->status,
81 sg_io->masked_status,
82 sg_io->msg_status,
83 sg_io->sb_len_wr,
84 sg_io->sbp,
85 sg_io->host_status,
86 sg_io->driver_status,
87 sg_io->resid,
88 sg_io->duration);
89
90 sg_io->dxfer_direction = -3;
91
92 ioctl(-1, SG_IO, sg_io);
93 printf("ioctl(-1, SG_IO, {interface_id='S'"
94 ", dxfer_direction=SG_DXFER_FROM_DEV"
95 ", cmd_len=%u"
96 ", cmdp=%p"
97 ", mx_sb_len=%u"
98 ", iovec_count=%u"
99 ", dxfer_len=%u"
100 ", timeout=%u"
101 ", flags=SG_FLAG_DIRECT_IO|SG_FLAG_UNUSED_LUN_INHIBIT"
102 "|SG_FLAG_MMAP_IO|SG_FLAG_NO_DXFER"
103 "|SG_FLAG_Q_AT_TAIL|SG_FLAG_Q_AT_HEAD|0xfffeffc8"
104 ", dxferp=%p"
105 ", status=%#x"
106 ", masked_status=%#x"
107 ", msg_status=%#x"
108 ", sb_len_wr=%u"
109 ", sbp=%p"
110 ", host_status=%#x"
111 ", driver_status=%#x"
112 ", resid=%d"
113 ", duration=%u"
114 ", info=SG_INFO_CHECK|SG_INFO_DIRECT_IO|SG_INFO_MIXED_IO|0xfffffff8"
115 "}) = -1 EBADF (%m)\n",
116 sg_io->cmd_len,
117 sg_io->cmdp,
118 sg_io->mx_sb_len,
119 sg_io->iovec_count,
120 sg_io->dxfer_len,
121 sg_io->timeout,
122 sg_io->dxferp,
123 sg_io->status,
124 sg_io->masked_status,
125 sg_io->msg_status,
126 sg_io->sb_len_wr,
127 sg_io->sbp,
128 sg_io->host_status,
129 sg_io->driver_status,
130 sg_io->resid,
131 sg_io->duration);
132
133 const struct iovec iov[] = {
134 {
135 .iov_base = (void *) efault - 2,
136 .iov_len = 2
137 }, {
138 .iov_base = (void *) efault - 3,
139 .iov_len = 4
140 }
141 };
142 struct iovec *const t_iov = tail_memdup(iov, sizeof(iov));
143
144 sg_io->flags = 0x24;
145 sg_io->info = 1;
146 sg_io->dxfer_direction = -2;
147
148 sg_io->iovec_count = ARRAY_SIZE(iov);
149 sg_io->dxfer_len = iov[0].iov_len + iov[1].iov_len - 1;
150 sg_io->dxferp = t_iov;
151
152 ioctl(-1, SG_IO, sg_io);
153 printf("ioctl(-1, SG_IO, {interface_id='S'"
154 ", dxfer_direction=SG_DXFER_TO_DEV"
155 ", cmd_len=%u"
156 ", cmdp=%p"
157 ", mx_sb_len=%u"
158 ", iovec_count=%u"
159 ", dxfer_len=%u"
160 ", timeout=%u"
161 ", flags=SG_FLAG_MMAP_IO|SG_FLAG_Q_AT_HEAD"
162 ", dxferp=[{iov_base=\"\\%o\\%o\", iov_len=%u}"
163 ", {iov_base=\"\\%o\\%o\\%o\", iov_len=%u}]"
164 ", status=%#x"
165 ", masked_status=%#x"
166 ", msg_status=%#x"
167 ", sb_len_wr=%u"
168 ", sbp=%p"
169 ", host_status=%#x"
170 ", driver_status=%#x"
171 ", resid=%d"
172 ", duration=%u"
173 ", info=SG_INFO_CHECK"
174 "}) = -1 EBADF (%m)\n",
175 sg_io->cmd_len,
176 sg_io->cmdp,
177 sg_io->mx_sb_len,
178 sg_io->iovec_count,
179 sg_io->dxfer_len,
180 sg_io->timeout,
181 *(unsigned char *) (iov[0].iov_base + 0),
182 *(unsigned char *) (iov[0].iov_base + 1),
183 (unsigned int) iov[0].iov_len,
184 *(unsigned char *) (iov[1].iov_base + 0),
185 *(unsigned char *) (iov[1].iov_base + 1),
186 *(unsigned char *) (iov[1].iov_base + 2),
187 (unsigned int) iov[1].iov_len,
188 sg_io->status,
189 sg_io->masked_status,
190 sg_io->msg_status,
191 sg_io->sb_len_wr,
192 sg_io->sbp,
193 sg_io->host_status,
194 sg_io->driver_status,
195 sg_io->resid,
196 sg_io->duration);
197
198 sg_io->flags = 0x11;
199 sg_io->dxfer_direction = -3;
200 sg_io->resid = sg_io->dxfer_len + 1;
201
202 ioctl(-1, SG_IO, sg_io);
203 printf("ioctl(-1, SG_IO, {interface_id='S'"
204 ", dxfer_direction=SG_DXFER_FROM_DEV"
205 ", cmd_len=%u"
206 ", cmdp=%p"
207 ", mx_sb_len=%u"
208 ", iovec_count=%u"
209 ", dxfer_len=%u"
210 ", timeout=%u"
211 ", flags=SG_FLAG_DIRECT_IO|SG_FLAG_Q_AT_TAIL"
212 ", dxferp=[{iov_base=\"\\%o\\%o\", iov_len=%u}"
213 ", {iov_base=\"\\%o\\%o\\%o\", iov_len=%u}]"
214 ", status=%#x"
215 ", masked_status=%#x"
216 ", msg_status=%#x"
217 ", sb_len_wr=%u"
218 ", sbp=%p"
219 ", host_status=%#x"
220 ", driver_status=%#x"
221 ", resid=%d"
222 ", duration=%u"
223 ", info=SG_INFO_CHECK"
224 "}) = -1 EBADF (%m)\n",
225 sg_io->cmd_len,
226 sg_io->cmdp,
227 sg_io->mx_sb_len,
228 sg_io->iovec_count,
229 sg_io->dxfer_len,
230 sg_io->timeout,
231 *(unsigned char *) (iov[0].iov_base + 0),
232 *(unsigned char *) (iov[0].iov_base + 1),
233 (unsigned int) iov[0].iov_len,
234 *(unsigned char *) (iov[1].iov_base + 0),
235 *(unsigned char *) (iov[1].iov_base + 1),
236 *(unsigned char *) (iov[1].iov_base + 2),
237 (unsigned int) iov[1].iov_len,
238 sg_io->status,
239 sg_io->masked_status,
240 sg_io->msg_status,
241 sg_io->sb_len_wr,
242 sg_io->sbp,
243 sg_io->host_status,
244 sg_io->driver_status,
245 sg_io->resid,
246 sg_io->duration);
247
248 sg_io->flags = 0x10000;
249 sg_io->info = 0xdeadbeef;
250 sg_io->iovec_count = 0;
251 sg_io->dxfer_len = 5;
252 sg_io->resid = 1;
253 sg_io->dxferp = (void *) efault - (sg_io->dxfer_len - sg_io->resid);
254
255 ioctl(-1, SG_IO, sg_io);
256 printf("ioctl(-1, SG_IO, {interface_id='S'"
257 ", dxfer_direction=SG_DXFER_FROM_DEV"
258 ", cmd_len=%u"
259 ", cmdp=%p"
260 ", mx_sb_len=%u"
261 ", iovec_count=%u"
262 ", dxfer_len=%u"
263 ", timeout=%u"
264 ", flags=SG_FLAG_NO_DXFER"
265 ", dxferp=\"\\x%x\\x%x\\x%x\\x%x\""
266 ", status=%#x"
267 ", masked_status=%#x"
268 ", msg_status=%#x"
269 ", sb_len_wr=%u"
270 ", sbp=%p"
271 ", host_status=%#x"
272 ", driver_status=%#x"
273 ", resid=%d"
274 ", duration=%u"
275 ", info=SG_INFO_CHECK|SG_INFO_DIRECT_IO|SG_INFO_MIXED_IO|0xdeadbee8"
276 "}) = -1 EBADF (%m)\n",
277 sg_io->cmd_len,
278 sg_io->cmdp,
279 sg_io->mx_sb_len,
280 sg_io->iovec_count,
281 sg_io->dxfer_len,
282 sg_io->timeout,
283 *(unsigned char *) (sg_io->dxferp + 0),
284 *(unsigned char *) (sg_io->dxferp + 1),
285 *(unsigned char *) (sg_io->dxferp + 2),
286 *(unsigned char *) (sg_io->dxferp + 3),
287 sg_io->status,
288 sg_io->masked_status,
289 sg_io->msg_status,
290 sg_io->sb_len_wr,
291 sg_io->sbp,
292 sg_io->host_status,
293 sg_io->driver_status,
294 sg_io->resid,
295 sg_io->duration);
296
297 sg_io->flags = 2;
298 sg_io->dxfer_direction = -4;
299 sg_io->dxfer_len = 3;
300 sg_io->resid = 1;
301 sg_io->dxferp = (void *) efault - sg_io->dxfer_len;
302
303 ioctl(-1, SG_IO, sg_io);
304 printf("ioctl(-1, SG_IO, {interface_id='S'"
305 ", dxfer_direction=SG_DXFER_TO_FROM_DEV"
306 ", cmd_len=%u"
307 ", cmdp=%p"
308 ", mx_sb_len=%u"
309 ", iovec_count=%u"
310 ", dxfer_len=%u"
311 ", timeout=%u"
312 ", flags=SG_FLAG_UNUSED_LUN_INHIBIT"
313 ", dxferp=\"\\x%x\\x%x\\x%x\" => dxferp=\"\\x%x\\x%x\""
314 ", status=%#x"
315 ", masked_status=%#x"
316 ", msg_status=%#x"
317 ", sb_len_wr=%u"
318 ", sbp=%p"
319 ", host_status=%#x"
320 ", driver_status=%#x"
321 ", resid=%d"
322 ", duration=%u"
323 ", info=SG_INFO_CHECK|SG_INFO_DIRECT_IO|SG_INFO_MIXED_IO|0xdeadbee8"
324 "}) = -1 EBADF (%m)\n",
325 sg_io->cmd_len,
326 sg_io->cmdp,
327 sg_io->mx_sb_len,
328 sg_io->iovec_count,
329 sg_io->dxfer_len,
330 sg_io->timeout,
331 *(unsigned char *) (sg_io->dxferp + 0),
332 *(unsigned char *) (sg_io->dxferp + 1),
333 *(unsigned char *) (sg_io->dxferp + 2),
334 *(unsigned char *) (sg_io->dxferp + 0),
335 *(unsigned char *) (sg_io->dxferp + 1),
336 sg_io->status,
337 sg_io->masked_status,
338 sg_io->msg_status,
339 sg_io->sb_len_wr,
340 sg_io->sbp,
341 sg_io->host_status,
342 sg_io->driver_status,
343 sg_io->resid,
344 sg_io->duration);
345
346 sg_io->flags = 0;
347 sg_io->resid = sg_io->dxfer_len;
348
349 ioctl(-1, SG_IO, sg_io);
350 printf("ioctl(-1, SG_IO, {interface_id='S'"
351 ", dxfer_direction=SG_DXFER_TO_FROM_DEV"
352 ", cmd_len=%u"
353 ", cmdp=%p"
354 ", mx_sb_len=%u"
355 ", iovec_count=%u"
356 ", dxfer_len=%u"
357 ", timeout=%u"
358 ", flags=0"
359 ", dxferp=\"\\x%x\\x%x\\x%x\""
360 ", status=%#x"
361 ", masked_status=%#x"
362 ", msg_status=%#x"
363 ", sb_len_wr=%u"
364 ", sbp=%p"
365 ", host_status=%#x"
366 ", driver_status=%#x"
367 ", resid=%d"
368 ", duration=%u"
369 ", info=SG_INFO_CHECK|SG_INFO_DIRECT_IO|SG_INFO_MIXED_IO|0xdeadbee8"
370 "}) = -1 EBADF (%m)\n",
371 sg_io->cmd_len,
372 sg_io->cmdp,
373 sg_io->mx_sb_len,
374 sg_io->iovec_count,
375 sg_io->dxfer_len,
376 sg_io->timeout,
377 *(unsigned char *) (sg_io->dxferp + 0),
378 *(unsigned char *) (sg_io->dxferp + 1),
379 *(unsigned char *) (sg_io->dxferp + 2),
380 sg_io->status,
381 sg_io->masked_status,
382 sg_io->msg_status,
383 sg_io->sb_len_wr,
384 sg_io->sbp,
385 sg_io->host_status,
386 sg_io->driver_status,
387 sg_io->resid,
388 sg_io->duration);
389
390 puts("+++ exited with 0 +++");
391 return 0;
392 }
393
394 #else
395
396 SKIP_MAIN_UNDEFINED("HAVE_SCSI_SG_H")
397
398 #endif