1 /* 2 * Check decoding of ioctl SG_IO v4 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_LINUX_BSG_H 33 34 # include <inttypes.h> 35 # include <stdio.h> 36 # include <sys/ioctl.h> 37 # include <sys/uio.h> 38 # include <linux/bsg.h> 39 40 # include "xlat/scsi_sg_commands.h" 41 42 int 43 main(void) 44 { 45 ioctl(-1, SG_IO, 0); 46 printf("ioctl(-1, SG_IO, NULL) = -1 EBADF (%m)\n"); 47 48 struct sg_io_v4 *const sg_io = tail_alloc(sizeof(*sg_io)); 49 fill_memory(sg_io, sizeof(*sg_io)); 50 51 const void *const efault = sg_io + 1; 52 ioctl(-1, SG_IO, efault); 53 printf("ioctl(-1, SG_IO, %p) = -1 EBADF (%m)\n", efault); 54 55 ioctl(-1, SG_IO, sg_io); 56 printf("ioctl(-1, SG_IO, [%u]) = -1 EBADF (%m)\n", sg_io->guard); 57 58 unsigned int *const pguard = tail_alloc(sizeof(*pguard)); 59 *pguard = (unsigned char) 'Q'; 60 ioctl(-1, SG_IO, pguard); 61 printf("ioctl(-1, SG_IO, {guard='Q', %p}) = -1 EBADF (%m)\n", pguard + 1); 62 63 sg_io->guard = (unsigned char) 'Q'; 64 sg_io->protocol = 0; 65 sg_io->subprotocol = 1; 66 sg_io->flags = -1U; 67 sg_io->info = -1U; 68 sg_io->request = (kernel_ulong_t) 0xfacefeedfffffff1ULL; 69 sg_io->response = (kernel_ulong_t) 0xfacefeedfffffff2ULL; 70 sg_io->dout_xferp = (kernel_ulong_t) 0xfacefeedfffffff3ULL; 71 sg_io->din_xferp = (kernel_ulong_t) 0xfacefeedfffffff4ULL; 72 ioctl(-1, SG_IO, sg_io); 73 printf("ioctl(-1, SG_IO, {guard='Q'" 74 ", protocol=BSG_PROTOCOL_SCSI" 75 ", subprotocol=BSG_SUB_PROTOCOL_SCSI_TMF" 76 ", request_len=%u" 77 ", request=%#llx" 78 ", request_tag=%#" PRI__x64 79 ", request_attr=%u" 80 ", request_priority=%u" 81 ", request_extra=%u" 82 ", max_response_len=%u" 83 ", dout_iovec_count=%u" 84 ", dout_xfer_len=%u" 85 ", din_iovec_count=%u" 86 ", din_xfer_len=%u" 87 ", dout_xferp=%#llx" 88 ", timeout=%u" 89 ", flags=BSG_FLAG_Q_AT_TAIL|BSG_FLAG_Q_AT_HEAD|0xffffffcf" 90 ", usr_ptr=%#" PRI__x64 91 ", response_len=%u" 92 ", response=%#llx" 93 ", din_xferp=%#llx" 94 ", driver_status=%#x" 95 ", transport_status=%#x" 96 ", device_status=%#x" 97 ", retry_delay=%u" 98 ", info=SG_INFO_CHECK|SG_INFO_DIRECT_IO|SG_INFO_MIXED_IO|0xfffffff8" 99 ", duration=%u" 100 ", response_len=%u" 101 ", din_resid=%d" 102 ", dout_resid=%d" 103 ", generated_tag=%#" PRI__x64 "}) = -1 EBADF (%m)\n", 104 sg_io->request_len, 105 (unsigned long long) (kernel_ulong_t) sg_io->request, 106 sg_io->request_tag, 107 sg_io->request_attr, 108 sg_io->request_priority, 109 sg_io->request_extra, 110 sg_io->max_response_len, 111 sg_io->dout_iovec_count, 112 sg_io->dout_xfer_len, 113 sg_io->din_iovec_count, 114 sg_io->din_xfer_len, 115 (unsigned long long) (kernel_ulong_t) sg_io->dout_xferp, 116 sg_io->timeout, 117 sg_io->usr_ptr, 118 sg_io->response_len, 119 (unsigned long long) (kernel_ulong_t) sg_io->response, 120 (unsigned long long) (kernel_ulong_t) sg_io->din_xferp, 121 sg_io->driver_status, 122 sg_io->transport_status, 123 sg_io->device_status, 124 sg_io->retry_delay, 125 sg_io->duration, 126 sg_io->response_len, 127 sg_io->din_resid, 128 sg_io->dout_resid, 129 sg_io->generated_tag); 130 131 const struct iovec iov[] = { 132 { 133 .iov_base = (void *) efault - 2, 134 .iov_len = 2 135 }, { 136 .iov_base = (void *) efault - 3, 137 .iov_len = 4 138 } 139 }; 140 const struct iovec *const t_iov = tail_memdup(iov, sizeof(iov)); 141 sg_io->dout_iovec_count = ARRAY_SIZE(iov); 142 sg_io->dout_xfer_len = iov[0].iov_len + iov[1].iov_len - 1; 143 sg_io->dout_xferp = (unsigned long) t_iov; 144 145 sg_io->din_iovec_count = 0; 146 sg_io->din_xfer_len = 5; 147 sg_io->din_resid = 1; 148 sg_io->din_xferp = (unsigned long) efault - 149 (sg_io->dout_xfer_len - sg_io->din_resid); 150 151 sg_io->request_len = 3; 152 sg_io->request = (unsigned long) efault - sg_io->request_len; 153 sg_io->response_len = 2; 154 sg_io->response = (unsigned long) efault - sg_io->response_len; 155 156 sg_io->flags = 0x20; 157 sg_io->info = 1; 158 159 ioctl(-1, SG_IO, sg_io); 160 printf("ioctl(-1, SG_IO, {guard='Q'" 161 ", protocol=BSG_PROTOCOL_SCSI" 162 ", subprotocol=BSG_SUB_PROTOCOL_SCSI_TMF" 163 ", request_len=%u" 164 ", request=\"\\x%x\\x%x\\x%x\"" 165 ", request_tag=%#" PRI__x64 166 ", request_attr=%u" 167 ", request_priority=%u" 168 ", request_extra=%u" 169 ", max_response_len=%u" 170 ", dout_iovec_count=%u" 171 ", dout_xfer_len=%u" 172 ", din_iovec_count=%u" 173 ", din_xfer_len=%u" 174 ", dout_xferp=[{iov_base=\"\\%o\\%o\", iov_len=%u}" 175 ", {iov_base=\"\\%o\\%o\\%o\", iov_len=%u}]" 176 ", timeout=%u, flags=BSG_FLAG_Q_AT_HEAD" 177 ", usr_ptr=%#" PRI__x64 178 ", response_len=%u" 179 ", response=\"\\x%x\\x%x\"" 180 ", din_xferp=\"\\x%x\\x%x\\x%x\\x%x\"" 181 ", driver_status=%#x" 182 ", transport_status=%#x" 183 ", device_status=%#x" 184 ", retry_delay=%u" 185 ", info=SG_INFO_CHECK" 186 ", duration=%u" 187 ", response_len=%u" 188 ", din_resid=%d" 189 ", dout_resid=%d" 190 ", generated_tag=%#" PRI__x64 "}) = -1 EBADF (%m)\n", 191 sg_io->request_len, 192 * (unsigned char *) ((unsigned long) sg_io->request + 0), 193 * (unsigned char *) ((unsigned long) sg_io->request + 1), 194 * (unsigned char *) ((unsigned long) sg_io->request + 2), 195 sg_io->request_tag, 196 sg_io->request_attr, 197 sg_io->request_priority, 198 sg_io->request_extra, 199 sg_io->max_response_len, 200 sg_io->dout_iovec_count, 201 sg_io->dout_xfer_len, 202 sg_io->din_iovec_count, 203 sg_io->din_xfer_len, 204 * (unsigned char *) (iov[0].iov_base + 0), 205 * (unsigned char *) (iov[0].iov_base + 1), 206 (unsigned int) iov[0].iov_len, 207 * (unsigned char *) (iov[1].iov_base + 0), 208 * (unsigned char *) (iov[1].iov_base + 1), 209 * (unsigned char *) (iov[1].iov_base + 2), 210 (unsigned int) iov[1].iov_len, 211 sg_io->timeout, 212 sg_io->usr_ptr, 213 sg_io->response_len, 214 * (unsigned char *) ((unsigned long) sg_io->response + 0), 215 * (unsigned char *) ((unsigned long) sg_io->response + 1), 216 * (unsigned char *) ((unsigned long) sg_io->din_xferp + 0), 217 * (unsigned char *) ((unsigned long) sg_io->din_xferp + 1), 218 * (unsigned char *) ((unsigned long) sg_io->din_xferp + 2), 219 * (unsigned char *) ((unsigned long) sg_io->din_xferp + 3), 220 sg_io->driver_status, 221 sg_io->transport_status, 222 sg_io->device_status, 223 sg_io->retry_delay, 224 sg_io->duration, 225 sg_io->response_len, 226 sg_io->din_resid, 227 sg_io->dout_resid, 228 sg_io->generated_tag); 229 230 puts("+++ exited with 0 +++"); 231 return 0; 232 } 233 234 #else 235 236 SKIP_MAIN_UNDEFINED("HAVE_LINUX_BSG_H") 237 238 #endif 239