1 /* 2 * Check decoding of ioctl SG_IO v3 commands. 3 * 4 * Copyright (c) 2017 Dmitry V. Levin <ldv (at) 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 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