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 "{aio_data=%#" PRI__x64 ", aio_lio_opcode=IOCB_CMD_PREAD" 243 ", aio_reqprio=11, aio_fildes=0, aio_buf=%p, aio_nbytes=%u" 244 ", aio_offset=%" PRI__d64 245 "}, {aio_data=%#" PRI__x64 ", aio_lio_opcode=IOCB_CMD_PREAD" 246 ", aio_reqprio=22, aio_fildes=0, aio_buf=%p, aio_nbytes=%u" 247 ", aio_offset=%" PRI__d64 "}]) = %s\n", 248 *ctx, nr, 249 cb[0].aio_data, data0, sizeof_data0, cb[0].aio_offset, 250 cb[1].aio_data, data1, sizeof_data1, cb[1].aio_offset, 251 sprintrc(rc)); 252 253 rc = syscall(__NR_io_getevents, bogus_ctx, 254 (long) 0xca7faceddeadf00dLL, (long) 0xba5e1e505ca571e0LL, 255 ev + 1, NULL); 256 printf("io_getevents(%#lx, %ld, %ld, %p, NULL) = %s\n", 257 bogus_ctx, (long) 0xca7faceddeadf00dLL, 258 (long) 0xba5e1e505ca571e0LL, ev + 1, sprintrc(rc)); 259 260 rc = syscall(__NR_io_getevents, bogus_ctx, 261 (long) 0xca7faceddeadf00dLL, (long) 0xba5e1e505ca571e0LL, 262 NULL, ts + 1); 263 printf("io_getevents(%#lx, %ld, %ld, NULL, %p) = %s\n", 264 bogus_ctx, (long) 0xca7faceddeadf00dLL, 265 (long) 0xba5e1e505ca571e0LL, ts + 1, sprintrc(rc)); 266 267 ts->tv_sec = 0xdeadbeefU; 268 ts->tv_nsec = 0xfacefeedU; 269 rc = syscall(__NR_io_getevents, bogus_ctx, 0, 0, 0, ts); 270 printf("io_getevents(%#lx, 0, 0, NULL" 271 ", {tv_sec=%lld, tv_nsec=%llu}) = %s\n", 272 bogus_ctx, (long long) ts->tv_sec, 273 zero_extend_signed_to_ull(ts->tv_nsec), sprintrc(rc)); 274 275 ts->tv_sec = (time_t) 0xcafef00ddeadbeefLL; 276 ts->tv_nsec = (long) 0xbadc0dedfacefeedLL; 277 rc = syscall(__NR_io_getevents, bogus_ctx, 0, 0, 0, ts); 278 printf("io_getevents(%#lx, 0, 0, NULL" 279 ", {tv_sec=%lld, tv_nsec=%llu}) = %s\n", 280 bogus_ctx, (long long) ts->tv_sec, 281 zero_extend_signed_to_ull(ts->tv_nsec), sprintrc(rc)); 282 283 ts->tv_sec = 0; 284 ts->tv_nsec = 123456789; 285 rc = syscall(__NR_io_getevents, *ctx, nr, nr + 1, ev, ts); 286 printf("io_getevents(%#lx, %ld, %ld, [" 287 "{data=%#" PRI__x64 ", obj=%p, res=%u, res2=0}, " 288 "{data=%#" PRI__x64 ", obj=%p, res=%u, res2=0}" 289 "], {tv_sec=0, tv_nsec=123456789}) = %s\n", 290 *ctx, (long) nr, (long) (nr + 1), 291 cb[0].aio_data, &cb[0], sizeof_data0, 292 cb[1].aio_data, &cb[1], sizeof_data1, 293 sprintrc(rc)); 294 295 rc = syscall(__NR_io_cancel, bogus_ctx, NULL, NULL); 296 printf("io_cancel(%#lx, NULL, NULL) = %s\n", bogus_ctx, sprintrc(rc)); 297 298 rc = syscall(__NR_io_cancel, *ctx, cbc + 1, ev); 299 printf("io_cancel(%#lx, %p, %p) = %s\n", *ctx, cbc + 1, ev, 300 sprintrc(rc)); 301 302 rc = syscall(__NR_io_cancel, *ctx, cbc, ev); 303 printf("io_cancel(%#lx, {aio_data=%#" PRI__x64 304 ", aio_lio_opcode=IOCB_CMD_PREAD, aio_reqprio=99" 305 ", aio_fildes=-42}, %p) = %s\n", 306 *ctx, cbc->aio_data, ev, sprintrc(rc)); 307 308 rc = syscall(__NR_io_submit, (unsigned long) 0xfacef157beeff00dULL, 309 (long) 0xdeadc0defacefeedLL, NULL); 310 printf("io_submit(%#lx, %ld, NULL) = %s\n", 311 (long) 0xfacef157beeff00dULL, 312 (long) 0xdeadc0defacefeedLL, sprintrc(rc)); 313 314 rc = syscall(__NR_io_submit, *ctx, -1L, cbvs + nr); 315 printf("io_submit(%#lx, %ld, %p) = %s\n", 316 *ctx, -1L, cbvs + nr, sprintrc(rc)); 317 318 rc = syscall(__NR_io_submit, *ctx, 1057L, cbvs2); 319 printf("io_submit(%#lx, %ld, [" 320 "{aio_data=%#" PRI__x64 ", aio_key=%u" 321 ", aio_lio_opcode=%hu /* IOCB_CMD_??? */, aio_fildes=%d}" 322 ", {aio_key=%u, aio_lio_opcode=IOCB_CMD_PWRITE, aio_reqprio=%hd" 323 ", aio_fildes=%d, aio_buf=NULL" 324 ", aio_nbytes=%" PRI__u64 ", aio_offset=%" PRI__d64 325 # ifdef IOCB_FLAG_RESFD 326 ", aio_resfd=%d, aio_flags=%#x" 327 # endif 328 "}, {aio_key=%u, aio_lio_opcode=IOCB_CMD_PWRITE" 329 ", aio_reqprio=%hd, aio_fildes=%d, aio_buf=%#" PRI__x64 330 ", aio_nbytes=%" PRI__u64 ", aio_offset=%" PRI__d64 331 "}, {aio_key=%u, aio_lio_opcode=IOCB_CMD_PWRITE" 332 ", aio_reqprio=%hd, aio_fildes=%d" 333 ", aio_buf=\"\\0\\1\\2\\3%.28s\"..." 334 ", aio_nbytes=%" PRI__u64 ", aio_offset=%" PRI__d64 335 "}, {aio_key=%u, aio_lio_opcode=IOCB_CMD_PWRITEV" 336 ", aio_reqprio=%hd, aio_fildes=%d, aio_buf=%#" PRI__x64 337 ", aio_nbytes=%" PRI__u64 ", aio_offset=%" PRI__d64 338 "}, {NULL}, {%#lx}, %p]) = %s\n", 339 *ctx, 1057L, 340 cbv2[0].aio_data, cbv2[0].aio_key, 341 cbv2[0].aio_lio_opcode, cbv2[0].aio_fildes, 342 cbv2[1].aio_key, cbv2[1].aio_reqprio, cbv2[1].aio_fildes, 343 cbv2[1].aio_nbytes, cbv2[1].aio_offset, 344 # ifdef IOCB_FLAG_RESFD 345 cbv2[1].aio_resfd, cbv2[1].aio_flags, 346 # endif 347 cbv2[2].aio_key, cbv2[2].aio_reqprio, cbv2[2].aio_fildes, 348 cbv2[2].aio_buf, cbv2[2].aio_nbytes, cbv2[2].aio_offset, 349 cbv2[3].aio_key, cbv2[3].aio_reqprio, cbv2[3].aio_fildes, 350 data2 + 4, cbv2[3].aio_nbytes, cbv2[3].aio_offset, 351 cbv2[4].aio_key, cbv2[4].aio_reqprio, cbv2[4].aio_fildes, 352 cbv2[4].aio_buf, cbv2[4].aio_nbytes, cbv2[4].aio_offset, 353 cbvs2[6], cbvs2 + 7, sprintrc(rc)); 354 355 rc = syscall(__NR_io_submit, *ctx, nr, cbvs); 356 if (rc != (long) nr) 357 perror_msg_and_skip("io_submit"); 358 printf("io_submit(%#lx, %u, [" 359 "{aio_data=%#" PRI__x64 ", aio_lio_opcode=IOCB_CMD_PREADV" 360 ", aio_reqprio=%hd, aio_fildes=0, " 361 "aio_buf=[{iov_base=%p, iov_len=%u}" 362 ", {iov_base=%p, iov_len=%u}], aio_offset=%" PRI__d64 "}, " 363 "{aio_data=%#" PRI__x64 ", aio_lio_opcode=IOCB_CMD_PREADV" 364 ", aio_reqprio=%hd, aio_fildes=0" 365 ", aio_buf=[{iov_base=%p, iov_len=%u}" 366 ", {iov_base=%p, iov_len=%u}], aio_offset=%" PRI__d64 "}" 367 "]) = %s\n", 368 *ctx, nr, 369 cbv[0].aio_data, cbv[0].aio_reqprio, 370 iov0[0].iov_base, (unsigned int) iov0[0].iov_len, 371 iov0[1].iov_base, (unsigned int) iov0[1].iov_len, 372 cbv[0].aio_offset, 373 cbv[1].aio_data, cbv[1].aio_reqprio, 374 iov1[0].iov_base, (unsigned int) iov1[0].iov_len, 375 iov1[1].iov_base, (unsigned int) iov1[1].iov_len, 376 cbv[1].aio_offset, 377 sprintrc(rc)); 378 379 rc = syscall(__NR_io_destroy, bogus_ctx); 380 printf("io_destroy(%#lx) = %s\n", 381 bogus_ctx, sprintrc(rc)); 382 383 rc = syscall(__NR_io_destroy, *ctx); 384 printf("io_destroy(%#lx) = %s\n", *ctx, sprintrc(rc)); 385 386 puts("+++ exited with 0 +++"); 387 return 0; 388 } 389 390 #else 391 392 SKIP_MAIN_UNDEFINED("__NR_io_*") 393 394 #endif 395