1 /* 2 * Copyright (c) 2015-2016 Dmitry V. Levin <ldv (at) altlinux.org> 3 * Copyright (c) 2015-2017 The strace developers. 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. The name of the author may not be used to endorse or promote products 15 * derived from this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #include "tests.h" 30 #include <fcntl.h> 31 #include <inttypes.h> 32 #include <stdio.h> 33 #include <time.h> 34 #include <unistd.h> 35 #include <asm/unistd.h> 36 37 #if defined __NR_io_setup \ 38 && defined __NR_io_submit \ 39 && defined __NR_io_getevents \ 40 && defined __NR_io_cancel \ 41 && defined __NR_io_destroy 42 # include <linux/aio_abi.h> 43 44 int 45 main(void) 46 { 47 static const long bogus_ctx = 48 (long) 0xface1e55deadbeefLL; 49 50 static const char data2[] = 51 "\0\1\2\3cat test test test 0123456789abcdef"; 52 53 const unsigned int sizeof_data0 = 4096; 54 const unsigned int sizeof_data1 = 8192; 55 void *data0 = tail_alloc(sizeof_data0); 56 void *data1 = tail_alloc(sizeof_data1); 57 58 const struct iocb proto_cb[] = { 59 { 60 .aio_data = (unsigned long) 0xfeedface11111111ULL, 61 .aio_reqprio = 11, 62 .aio_buf = (unsigned long) data0, 63 .aio_offset = (unsigned long) 0xdeface1facefeedULL, 64 .aio_nbytes = sizeof_data0 65 }, 66 { 67 .aio_data = (unsigned long) 0xfeedface22222222ULL, 68 .aio_reqprio = 22, 69 .aio_buf = (unsigned long) data1, 70 .aio_offset = (unsigned long) 0xdeface2cafef00dULL, 71 .aio_nbytes = sizeof_data1 72 } 73 }; 74 const struct iocb *cb = tail_memdup(proto_cb, sizeof(proto_cb)); 75 76 const struct iovec proto_iov0[] = { 77 { 78 .iov_base = data0, 79 .iov_len = sizeof_data0 / 4 80 }, 81 { 82 .iov_base = data0 + sizeof_data0 / 4, 83 .iov_len = sizeof_data0 / 4 * 3 84 }, 85 }; 86 const struct iovec *iov0 = tail_memdup(proto_iov0, sizeof(proto_iov0)); 87 88 const struct iovec proto_iov1[] = { 89 { 90 .iov_base = data1, 91 .iov_len = sizeof_data1 / 4 92 }, 93 { 94 .iov_base = data1 + sizeof_data1 / 4, 95 .iov_len = sizeof_data1 / 4 * 3 96 }, 97 }; 98 const struct iovec *iov1 = tail_memdup(proto_iov1, sizeof(proto_iov1)); 99 100 const struct iocb proto_cbv[] = { 101 { 102 .aio_data = (unsigned long) 0xfeed11111111faceULL, 103 .aio_lio_opcode = 7, 104 .aio_reqprio = 111, 105 .aio_buf = (unsigned long) iov0, 106 .aio_offset = (unsigned long) 0xdeface1facefeedULL, 107 .aio_nbytes = ARRAY_SIZE(proto_iov0) 108 }, 109 { 110 .aio_data = (unsigned long) 0xfeed22222222faceULL, 111 .aio_lio_opcode = 7, 112 .aio_reqprio = 222, 113 .aio_buf = (unsigned long) iov1, 114 .aio_offset = (unsigned long) 0xdeface2cafef00dULL, 115 .aio_nbytes = ARRAY_SIZE(proto_iov1) 116 } 117 }; 118 const struct iocb *cbv = tail_memdup(proto_cbv, sizeof(proto_cbv)); 119 120 /* For additional decoder testing */ 121 const struct iocb proto_cbv2[] = { 122 { 123 .aio_data = 0xbadfacedc0ffeeedULL, 124 .aio_key = 0xdefaced0, 125 .aio_lio_opcode = 0xf00d, 126 .aio_reqprio = 0, 127 .aio_fildes = 0xdefaced1, 128 .aio_buf = 0, 129 }, 130 { 131 .aio_data = 0, 132 .aio_key = 0xdefaced0, 133 .aio_lio_opcode = 1, 134 .aio_reqprio = 0xbeef, 135 .aio_fildes = 0xdefaced1, 136 .aio_buf = 0, 137 /* In order to make record valid */ 138 .aio_nbytes = (size_t) 0x1020304050607080ULL, 139 .aio_offset = 0xdeadda7abadc0dedULL, 140 # ifdef IOCB_FLAG_RESFD 141 .aio_flags = 0xfacef157, 142 .aio_resfd = 0xded1ca7e, 143 # endif 144 }, 145 { 146 .aio_data = 0, 147 .aio_key = 0xdefaced0, 148 .aio_lio_opcode = 1, 149 .aio_reqprio = 0xbeef, 150 .aio_fildes = 0xdefaced1, 151 .aio_buf = 0xbadc0ffeedefacedULL, 152 .aio_nbytes = 0x8090a0b0c0d0e0f0ULL, 153 .aio_offset = 0xdeadda7abadc0dedULL, 154 }, 155 { 156 .aio_data = 0, 157 .aio_key = 0xdefaced0, 158 .aio_lio_opcode = 1, 159 .aio_reqprio = 0xbeef, 160 .aio_fildes = 0xdefaced1, 161 .aio_buf = (unsigned long)data2, 162 .aio_nbytes = sizeof(data2), 163 .aio_offset = 0xdeadda7abadc0dedULL, 164 }, 165 { 166 .aio_data = 0, 167 .aio_key = 0xdefaced0, 168 .aio_lio_opcode = 8, 169 .aio_reqprio = 0xbeef, 170 .aio_fildes = 0xdefaced1, 171 .aio_buf = 0, 172 .aio_nbytes = 0x8090a0b0c0d0e0f0ULL, 173 .aio_offset = 0xdeadda7abadc0dedULL, 174 }, 175 }; 176 const struct iocb *cbv2 = tail_memdup(proto_cbv2, sizeof(proto_cbv2)); 177 178 const struct iocb proto_cbc = { 179 .aio_data = (unsigned long) 0xdeadbeefbadc0dedULL, 180 .aio_reqprio = 99, 181 .aio_fildes = -42 182 }; 183 const struct iocb *cbc = tail_memdup(&proto_cbc, sizeof(proto_cbc)); 184 185 const long proto_cbs[] = { 186 (long) &cb[0], (long) &cb[1] 187 }; 188 const long *cbs = tail_memdup(proto_cbs, sizeof(proto_cbs)); 189 190 const long proto_cbvs[] = { 191 (long) &cbv[0], (long) &cbv[1], 192 }; 193 const long *cbvs = tail_memdup(proto_cbvs, sizeof(proto_cbvs)); 194 195 const long proto_cbvs2[] = { 196 (long) &cbv2[0], (long) &cbv2[1], (long) &cbv2[2], 197 (long) &cbv2[3], (long) &cbv2[4], 198 (long) NULL, (long) 0xffffffffffffffffLL, 199 }; 200 const long *cbvs2 = tail_memdup(proto_cbvs2, sizeof(proto_cbvs2)); 201 202 TAIL_ALLOC_OBJECT_CONST_PTR(unsigned long, ctx); 203 *ctx = 0; 204 205 const unsigned int nr = ARRAY_SIZE(proto_cb); 206 const unsigned long lnr = (unsigned long) (0xdeadbeef00000000ULL | nr); 207 208 const struct io_event *ev = tail_alloc(nr * sizeof(struct io_event)); 209 TAIL_ALLOC_OBJECT_CONST_PTR(struct timespec, ts); 210 211 (void) close(0); 212 if (open("/dev/zero", O_RDONLY)) 213 perror_msg_and_skip("open: %s", "/dev/zero"); 214 215 long rc = syscall(__NR_io_setup, 0xdeadbeef, NULL); 216 printf("io_setup(%u, NULL) = %s\n", 0xdeadbeef, sprintrc(rc)); 217 218 rc = syscall(__NR_io_setup, lnr, ctx + 1); 219 printf("io_setup(%u, %p) = %s\n", nr, ctx + 1, sprintrc(rc)); 220 221 if (syscall(__NR_io_setup, lnr, ctx)) 222 perror_msg_and_skip("io_setup"); 223 printf("io_setup(%u, [%#lx]) = 0\n", nr, *ctx); 224 225 rc = syscall(__NR_io_submit, bogus_ctx, (long) 0xca7faceddeadf00dLL, 226 NULL); 227 printf("io_submit(%#lx, %ld, NULL) = %s\n", 228 bogus_ctx, (long) 0xca7faceddeadf00dLL, sprintrc(rc)); 229 230 rc = syscall(__NR_io_submit, *ctx, nr, cbs + nr); 231 printf("io_submit(%#lx, %ld, %p) = %s\n", 232 *ctx, (long) nr, cbs + nr, sprintrc(rc)); 233 234 rc = syscall(__NR_io_submit, *ctx, -1L, cbs); 235 printf("io_submit(%#lx, -1, %p) = %s\n", 236 *ctx, cbs, sprintrc(rc)); 237 238 rc = syscall(__NR_io_submit, *ctx, nr, cbs); 239 if (rc != (long) nr) 240 perror_msg_and_skip("io_submit"); 241 printf("io_submit(%#lx, %u, [" 242 "{data=%#" PRI__x64 ", pread, reqprio=11, fildes=0, " 243 "buf=%p, nbytes=%u, offset=%" PRI__d64 "}, " 244 "{data=%#" PRI__x64 ", pread, reqprio=22, fildes=0, " 245 "buf=%p, nbytes=%u, offset=%" PRI__d64 "}" 246 "]) = %s\n", 247 *ctx, nr, 248 cb[0].aio_data, data0, sizeof_data0, cb[0].aio_offset, 249 cb[1].aio_data, data1, sizeof_data1, cb[1].aio_offset, 250 sprintrc(rc)); 251 252 rc = syscall(__NR_io_getevents, bogus_ctx, 253 (long) 0xca7faceddeadf00dLL, (long) 0xba5e1e505ca571e0LL, 254 ev + 1, NULL); 255 printf("io_getevents(%#lx, %ld, %ld, %p, NULL) = %s\n", 256 bogus_ctx, (long) 0xca7faceddeadf00dLL, 257 (long) 0xba5e1e505ca571e0LL, ev + 1, sprintrc(rc)); 258 259 rc = syscall(__NR_io_getevents, bogus_ctx, 260 (long) 0xca7faceddeadf00dLL, (long) 0xba5e1e505ca571e0LL, 261 NULL, ts + 1); 262 printf("io_getevents(%#lx, %ld, %ld, NULL, %p) = %s\n", 263 bogus_ctx, (long) 0xca7faceddeadf00dLL, 264 (long) 0xba5e1e505ca571e0LL, ts + 1, sprintrc(rc)); 265 266 ts->tv_sec = 0xdeadbeefU; 267 ts->tv_nsec = 0xfacefeedU; 268 rc = syscall(__NR_io_getevents, bogus_ctx, 0, 0, 0, ts); 269 printf("io_getevents(%#lx, 0, 0, NULL" 270 ", {tv_sec=%lld, tv_nsec=%llu}) = %s\n", 271 bogus_ctx, (long long) ts->tv_sec, 272 zero_extend_signed_to_ull(ts->tv_nsec), sprintrc(rc)); 273 274 ts->tv_sec = (time_t) 0xcafef00ddeadbeefLL; 275 ts->tv_nsec = (long) 0xbadc0dedfacefeedLL; 276 rc = syscall(__NR_io_getevents, bogus_ctx, 0, 0, 0, ts); 277 printf("io_getevents(%#lx, 0, 0, NULL" 278 ", {tv_sec=%lld, tv_nsec=%llu}) = %s\n", 279 bogus_ctx, (long long) ts->tv_sec, 280 zero_extend_signed_to_ull(ts->tv_nsec), sprintrc(rc)); 281 282 ts->tv_sec = 0; 283 ts->tv_nsec = 123456789; 284 rc = syscall(__NR_io_getevents, *ctx, nr, nr + 1, ev, ts); 285 printf("io_getevents(%#lx, %ld, %ld, [" 286 "{data=%#" PRI__x64 ", obj=%p, res=%u, res2=0}, " 287 "{data=%#" PRI__x64 ", obj=%p, res=%u, res2=0}" 288 "], {tv_sec=0, tv_nsec=123456789}) = %s\n", 289 *ctx, (long) nr, (long) (nr + 1), 290 cb[0].aio_data, &cb[0], sizeof_data0, 291 cb[1].aio_data, &cb[1], sizeof_data1, 292 sprintrc(rc)); 293 294 rc = syscall(__NR_io_cancel, bogus_ctx, NULL, NULL); 295 printf("io_cancel(%#lx, NULL, NULL) = %s\n", bogus_ctx, sprintrc(rc)); 296 297 rc = syscall(__NR_io_cancel, *ctx, cbc + 1, ev); 298 printf("io_cancel(%#lx, %p, %p) = %s\n", *ctx, cbc + 1, ev, 299 sprintrc(rc)); 300 301 rc = syscall(__NR_io_cancel, *ctx, cbc, ev); 302 printf("io_cancel(%#lx, {data=%#" PRI__x64 303 ", pread, reqprio=99, fildes=-42}, %p) = %s\n", 304 *ctx, cbc->aio_data, ev, sprintrc(rc)); 305 306 rc = syscall(__NR_io_submit, (unsigned long) 0xfacef157beeff00dULL, 307 (long) 0xdeadc0defacefeedLL, NULL); 308 printf("io_submit(%#lx, %ld, NULL) = %s\n", 309 (long) 0xfacef157beeff00dULL, 310 (long) 0xdeadc0defacefeedLL, sprintrc(rc)); 311 312 rc = syscall(__NR_io_submit, *ctx, -1L, cbvs + nr); 313 printf("io_submit(%#lx, %ld, %p) = %s\n", 314 *ctx, -1L, cbvs + nr, sprintrc(rc)); 315 316 rc = syscall(__NR_io_submit, *ctx, 1057L, cbvs2); 317 printf("io_submit(%#lx, %ld, [" 318 "{data=%#" PRI__x64 ", key=%u, %hu /* SUB_??? */, fildes=%d}, " 319 "{key=%u, pwrite, reqprio=%hd, fildes=%d, str=NULL" 320 ", nbytes=%" PRI__u64 ", offset=%" PRI__d64 321 # ifdef IOCB_FLAG_RESFD 322 ", resfd=%d, flags=%#x" 323 # endif 324 "}, " 325 "{key=%u, pwrite, reqprio=%hd, fildes=%d, buf=%#" PRI__x64 326 ", nbytes=%" PRI__u64 ", offset=%" PRI__d64 "}, " 327 "{key=%u, pwrite, reqprio=%hd, fildes=%d" 328 ", str=\"\\0\\1\\2\\3%.28s\"..." 329 ", nbytes=%" PRI__u64 ", offset=%" PRI__d64 "}, " 330 "{key=%u, pwritev, reqprio=%hd, fildes=%d, buf=%#" PRI__x64 331 ", nbytes=%" PRI__u64 ", offset=%" PRI__d64 "}" 332 ", {NULL}, {%#lx}, %p]) = %s\n", 333 *ctx, 1057L, 334 cbv2[0].aio_data, cbv2[0].aio_key, 335 cbv2[0].aio_lio_opcode, cbv2[0].aio_fildes, 336 cbv2[1].aio_key, cbv2[1].aio_reqprio, cbv2[1].aio_fildes, 337 cbv2[1].aio_nbytes, cbv2[1].aio_offset, 338 # ifdef IOCB_FLAG_RESFD 339 cbv2[1].aio_resfd, cbv2[1].aio_flags, 340 # endif 341 cbv2[2].aio_key, cbv2[2].aio_reqprio, cbv2[2].aio_fildes, 342 cbv2[2].aio_buf, cbv2[2].aio_nbytes, cbv2[2].aio_offset, 343 cbv2[3].aio_key, cbv2[3].aio_reqprio, cbv2[3].aio_fildes, 344 data2 + 4, cbv2[3].aio_nbytes, cbv2[3].aio_offset, 345 cbv2[4].aio_key, cbv2[4].aio_reqprio, cbv2[4].aio_fildes, 346 cbv2[4].aio_buf, cbv2[4].aio_nbytes, cbv2[4].aio_offset, 347 cbvs2[6], cbvs2 + 7, sprintrc(rc)); 348 349 rc = syscall(__NR_io_submit, *ctx, nr, cbvs); 350 if (rc != (long) nr) 351 perror_msg_and_skip("io_submit"); 352 printf("io_submit(%#lx, %u, [" 353 "{data=%#" PRI__x64 ", preadv, reqprio=%hd, fildes=0, " 354 "iovec=[{iov_base=%p, iov_len=%u}" 355 ", {iov_base=%p, iov_len=%u}], offset=%" PRI__d64 "}, " 356 "{data=%#" PRI__x64 ", preadv, reqprio=%hd, fildes=0, " 357 "iovec=[{iov_base=%p, iov_len=%u}" 358 ", {iov_base=%p, iov_len=%u}], offset=%" PRI__d64 "}" 359 "]) = %s\n", 360 *ctx, nr, 361 cbv[0].aio_data, cbv[0].aio_reqprio, 362 iov0[0].iov_base, (unsigned int) iov0[0].iov_len, 363 iov0[1].iov_base, (unsigned int) iov0[1].iov_len, 364 cbv[0].aio_offset, 365 cbv[1].aio_data, cbv[1].aio_reqprio, 366 iov1[0].iov_base, (unsigned int) iov1[0].iov_len, 367 iov1[1].iov_base, (unsigned int) iov1[1].iov_len, 368 cbv[1].aio_offset, 369 sprintrc(rc)); 370 371 rc = syscall(__NR_io_destroy, bogus_ctx); 372 printf("io_destroy(%#lx) = %s\n", 373 bogus_ctx, sprintrc(rc)); 374 375 rc = syscall(__NR_io_destroy, *ctx); 376 printf("io_destroy(%#lx) = %s\n", *ctx, sprintrc(rc)); 377 378 puts("+++ exited with 0 +++"); 379 return 0; 380 } 381 382 #else 383 384 SKIP_MAIN_UNDEFINED("__NR_io_*") 385 386 #endif 387