diff options
author | Eugene Syromyatnikov <evgsyr@gmail.com> | 2021-09-17 19:25:47 +0200 |
---|---|---|
committer | Eugene Syromyatnikov <evgsyr@gmail.com> | 2021-10-12 00:35:30 +0200 |
commit | 941792d08da6917c63243775be35429a21c2b36c (patch) | |
tree | 55d815c69c18f512b03eb85ed7f49f7c4e429a31 | |
parent | 0cf482530a95d6034b6987333fdd334dcd58308f (diff) | |
download | strace-941792d08da6917c63243775be35429a21c2b36c.tar.gz |
io_uring: decode struct io_uring_rsrc_register and io_uring_rsrc_update2
* src/io_uring.c (print_io_uring_rsrc_data, print_io_uring_rsrc_tags,
print_io_uring_register_rsrc, print_io_uring_update_rsrc): New functions.
(SYS_FUNC(io_uring_register)) <case IORING_REGISTER_FILES2,
case IORING_REGISTER_BUFFERS2>: Call print_io_uring_register_rsrc.
(SYS_FUNC(io_uring_register)) <case IORING_REGISTER_FILES_UPDATE2,
case IORING_REGISTER_BUFFERS_UPDATE>: Call print_io_uring_update_rsrc.
* tests/io_uring_register.c (BIG_ADDR_MASK): New macro.
(path_null, path_full): New constants, moved out of main.
(print_rsrc_data, print_rsrc_tags): New functions.
(main): Add checks for new decoders.
-rw-r--r-- | src/io_uring.c | 141 | ||||
-rw-r--r-- | tests/io_uring_register.c | 291 |
2 files changed, 430 insertions, 2 deletions
diff --git a/src/io_uring.c b/src/io_uring.c index 67c2d3d5a..8ef8bb29c 100644 --- a/src/io_uring.c +++ b/src/io_uring.c @@ -337,6 +337,139 @@ print_io_uring_restrictions(struct tcb *tcp, const kernel_ulong_t addr, tfetch_mem, print_io_uring_restriction, NULL); } +static void +print_io_uring_rsrc_data(struct tcb *tcp, const uint64_t data, + const unsigned int nr, const unsigned int opcode) +{ + int fd_buf; + + switch (opcode) { + case IORING_REGISTER_FILES2: + case IORING_REGISTER_BUFFERS2: + case IORING_REGISTER_BUFFERS_UPDATE: + case IORING_REGISTER_FILES_UPDATE2: + tprint_struct_next(); + tprints_field_name("data"); + print_big_u64_addr(data); + break; + } + + switch (opcode) { + case IORING_REGISTER_FILES2: + print_array(tcp, data, nr, &fd_buf, sizeof(fd_buf), + tfetch_mem, print_fd_array_member, NULL); + break; + case IORING_REGISTER_FILES_UPDATE2: + print_array(tcp, data, nr, &fd_buf, sizeof(fd_buf), + tfetch_mem, print_files_update_array_member, NULL); + break; + case IORING_REGISTER_BUFFERS2: + case IORING_REGISTER_BUFFERS_UPDATE: + tprint_iov(tcp, nr, data, iov_decode_addr); + break; + } +} + +static void +print_io_uring_rsrc_tags(struct tcb *tcp, const uint64_t tags, + const unsigned int nr) +{ + uint64_t tag_buf; + + tprint_struct_next(); + tprints_field_name("tags"); + print_big_u64_addr(tags); + print_array(tcp, tags, nr, &tag_buf, sizeof(tag_buf), + tfetch_mem, print_xint_array_member, NULL); +} + +static void +print_io_uring_register_rsrc(struct tcb *tcp, const kernel_ulong_t addr, + const unsigned int size, const unsigned int opcode) +{ + struct io_uring_rsrc_register arg; + CHECK_TYPE_SIZE(arg, 32); + CHECK_TYPE_SIZE(arg.resv, sizeof(uint32_t)); + CHECK_TYPE_SIZE(arg.resv2, sizeof(uint64_t)); + + if (size < 32) { + printaddr(addr); + return; + } + + if (umove_or_printaddr(tcp, addr, &arg)) + return; + + tprint_struct_begin(); + PRINT_FIELD_U(arg, nr); + + if (arg.resv) { + tprint_struct_next(); + PRINT_FIELD_X(arg, resv); + } + + if (arg.resv2) { + tprint_struct_next(); + PRINT_FIELD_X(arg, resv2); + } + + print_io_uring_rsrc_data(tcp, arg.data, arg.nr, opcode); + + print_io_uring_rsrc_tags(tcp, arg.tags, arg.nr); + + if (size > sizeof(arg)) { + print_nonzero_bytes(tcp, tprint_struct_next, addr, sizeof(arg), + MIN(size, get_pagesize()), QUOTE_FORCE_HEX); + } + + tprint_struct_end(); +} + +static void +print_io_uring_update_rsrc(struct tcb *tcp, const kernel_ulong_t addr, + const unsigned int size, const unsigned int opcode) +{ + struct io_uring_rsrc_update2 arg; + CHECK_TYPE_SIZE(arg, 32); + CHECK_TYPE_SIZE(arg.resv, sizeof(uint32_t)); + CHECK_TYPE_SIZE(arg.resv2, sizeof(uint32_t)); + + if (size < 32) { + printaddr(addr); + return; + } + + if (umove_or_printaddr(tcp, addr, &arg)) + return; + + tprint_struct_begin(); + PRINT_FIELD_U(arg, offset); + + if (arg.resv) { + tprint_struct_next(); + PRINT_FIELD_X(arg, resv); + } + + print_io_uring_rsrc_data(tcp, arg.data, arg.nr, opcode); + + print_io_uring_rsrc_tags(tcp, arg.tags, arg.nr); + + tprint_struct_next(); + PRINT_FIELD_U(arg, nr); + + if (arg.resv2) { + tprint_struct_next(); + PRINT_FIELD_X(arg, resv2); + } + + if (size > sizeof(arg)) { + print_nonzero_bytes(tcp, tprint_struct_next, addr, sizeof(arg), + MIN(size, get_pagesize()), QUOTE_FORCE_HEX); + } + + tprint_struct_end(); +} + SYS_FUNC(io_uring_register) { const int fd = tcp->u_arg[0]; @@ -377,6 +510,14 @@ SYS_FUNC(io_uring_register) case IORING_REGISTER_RESTRICTIONS: print_io_uring_restrictions(tcp, arg, nargs); break; + case IORING_REGISTER_FILES2: + case IORING_REGISTER_BUFFERS2: + print_io_uring_register_rsrc(tcp, arg, nargs, opcode); + break; + case IORING_REGISTER_FILES_UPDATE2: + case IORING_REGISTER_BUFFERS_UPDATE: + print_io_uring_update_rsrc(tcp, arg, nargs, opcode); + break; case IORING_UNREGISTER_BUFFERS: case IORING_UNREGISTER_FILES: case IORING_UNREGISTER_EVENTFD: diff --git a/tests/io_uring_register.c b/tests/io_uring_register.c index ba050087b..f800311d2 100644 --- a/tests/io_uring_register.c +++ b/tests/io_uring_register.c @@ -21,14 +21,20 @@ /* From tests/bpf.c */ #if defined MPERS_IS_m32 || SIZEOF_KERNEL_LONG_T > 4 # define BIG_ADDR_MAYBE(addr_) +# define BIG_ADDR_MASK 0 #elif defined __arm__ || defined __i386__ || defined __mips__ \ || defined __powerpc__ || defined __riscv__ || defined __s390__ \ || defined __sparc__ || defined __tile__ # define BIG_ADDR_MAYBE(addr_) addr_ " or " +# define BIG_ADDR_MASK 0xffffffff00000000ULL #else # define BIG_ADDR_MAYBE(addr_) +# define BIG_ADDR_MASK 0 #endif +static const char path_null[] = "/dev/null"; +static const char path_full[] = "/dev/full"; + static const char *errstr; static long @@ -49,11 +55,79 @@ sys_io_uring_register(unsigned int fd, unsigned int opcode, return rc; } +static void +print_rsrc_data(const struct iovec *arg_iov, const struct iovec *iov, + const int *arg_fds, const int *fds, const size_t i, + const size_t j, const void *endptr, bool upd) +{ + printf(", data="); + if (BIG_ADDR_MASK && (j & 2)) { + printf("%#llx or ", (unsigned long long) (BIG_ADDR_MASK | + (j & 1 ? i ? (uintptr_t) arg_iov + : (uintptr_t) arg_fds : 0))); + } + if (!(j & 1)) { + printf("NULL"); + return; + } + + printf("["); + if (!(j & 32)) + goto print_rsrc_data_end; + if (i) { + printf("{iov_base=%p, iov_len=%lu}, {iov_base=%p, iov_len=%lu}", + iov[0].iov_base, (unsigned long) iov[0].iov_len, + iov[1].iov_base, (unsigned long) iov[1].iov_len); + } else { + printf("%u<%s>, %u<%s>, -1, %s, -3", + fds[0], path_full, fds[1], path_null, + upd ? XLAT_KNOWN(-2, "IORING_REGISTER_FILES_SKIP") + : "-2"); + } + if (j & 16) + printf(", ... /* %p */", endptr); +print_rsrc_data_end: + printf("]"); +} + +static void +print_rsrc_tags(const uint64_t *arg_tags, const uint64_t *tags, const size_t i, + const size_t j, const void *endptr) +{ + printf(", tags="); + if (BIG_ADDR_MASK && (j & 8)) { + printf("%#llx or ", (unsigned long long) ( + BIG_ADDR_MASK | (j & 4 ? 0 + : (uintptr_t) (arg_tags + 1 + i * 3 - !!(j & 64))))); + } + if (j & 4) { + printf("NULL"); + return; + } + + printf("["); + if (!(j & 32)) + goto print_rsrc_tags_end; + if (i) { + printf("%s0xbadc0deddadfaced%s", + j & 64 ? "0xfacefeed, " : "", j & 64 ? "" : ", 0"); + } else { + printf("%s0x1, 0xdead, 0xfacefeed, 0xbadc0deddadfaced%s", + j & 64 ? "0x1337, " : "", j & 64 ? "" : ", 0"); + } + if (j & 16) { + if (j & 64) + printf(", 0"); + else + printf(", ... /* %p */", endptr); + } +print_rsrc_tags_end: + printf("]"); +} + int main(void) { - static const char path_null[] = "/dev/null"; - static const char path_full[] = "/dev/full"; const struct iovec iov[] = { { .iov_base = (void *) (unsigned long) 0xfacefeedcafef00d, @@ -496,6 +570,219 @@ main(void) ARRAY_SIZE(restrictions_data) + !!(j == 1), errstr); } + + /* IORING_REGISTER_FILES2, IORING_REGISTER_BUFFERS2 */ + static const struct { + unsigned int op; + const char *str; + } rsrc_reg_ops[] = { + { 13, "IORING_REGISTER_FILES2" }, + { 15, "IORING_REGISTER_BUFFERS2" }, + }; + static const uint64_t tags[] = { 0x1337, 1, 0xdead, 0xfacefeed, + 0xbadc0deddadfacedULL, 0 }; + const uint64_t *arg_tags = tail_memdup(tags, sizeof(tags)); + + struct io_uring_rsrc_register *bogus_rsrc_reg = tail_alloc(24); + struct io_uring_rsrc_register *rsrc_reg = tail_alloc(sizeof(*rsrc_reg)); + struct io_uring_rsrc_register *big_rsrc_reg = + tail_alloc(sizeof(*big_rsrc_reg) + 8); + + fill_memory(big_rsrc_reg, sizeof(*big_rsrc_reg) + 8); + + for (size_t i = 0; i < ARRAY_SIZE(rsrc_reg_ops); i++) { + sys_io_uring_register(fd_null, rsrc_reg_ops[i].op, 0, + 0xdeadbeef); + printf("io_uring_register(%u<%s>, " XLAT_FMT ", NULL, %u)" + " = %s\n", + fd_null, path_null, + XLAT_SEL(rsrc_reg_ops[i].op, rsrc_reg_ops[i].str), + 0xdeadbeef, errstr); + + struct { + void *ptr; + unsigned int sz; + } ptr_args[] = { + { bogus_rsrc_reg, 24 }, + { bogus_rsrc_reg, 32 }, + }; + for (size_t j = 0; j < ARRAY_SIZE(ptr_args); j++) { + sys_io_uring_register(fd_null, rsrc_reg_ops[i].op, + ptr_args[j].ptr, ptr_args[j].sz); + printf("io_uring_register(%u<%s>, " XLAT_FMT ", %p, %u)" + " = %s\n", + fd_null, path_null, + XLAT_SEL(rsrc_reg_ops[i].op, + rsrc_reg_ops[i].str), + ptr_args[j].ptr, ptr_args[j].sz, errstr); + } + + for (size_t j = 0; j < 256; j++) { + void *endptr = i ? (void *) (arg_iov + ARRAY_SIZE(iov)) + : (void *) (arg_fds + ARRAY_SIZE(fds)); + + rsrc_reg->data = i ? (uintptr_t) arg_iov + : (uintptr_t) arg_fds; + rsrc_reg->nr = i ? ARRAY_SIZE(iov) : ARRAY_SIZE(fds); + rsrc_reg->tags = (uintptr_t) (arg_tags + + ARRAY_SIZE(tags) + - rsrc_reg->nr); + + rsrc_reg->data &= ~-!(j & 1); + rsrc_reg->data |= j & 2 ? BIG_ADDR_MASK : 0; + rsrc_reg->tags -= !!(j & 64) * sizeof(uint64_t); + rsrc_reg->tags &= ~-!!(j & 4); + rsrc_reg->tags |= j & 8 ? BIG_ADDR_MASK : 0; + rsrc_reg->nr += !!(j & 16); + rsrc_reg->nr &= ~-!(j & 32); + + rsrc_reg->resv = j & 64 ? 0xbadc0ded : 0; + rsrc_reg->resv2 = j & 128 ? 0xfacecafebeeffeedULL : 0; + + memcpy(big_rsrc_reg, rsrc_reg, sizeof(*rsrc_reg)); + + for (size_t k = 1; k < 5; k++) { + sys_io_uring_register(fd_null, + rsrc_reg_ops[i].op, + k > 2 ? big_rsrc_reg + : rsrc_reg, + sizeof(*rsrc_reg) + + (k / 2) * 8); + printf("io_uring_register(%u<%s>, " XLAT_FMT + ", {nr=%zu%s%s", + fd_null, path_null, + XLAT_SEL(rsrc_reg_ops[i].op, + rsrc_reg_ops[i].str), + j & 32 ? (i ? ARRAY_SIZE(iov) + : ARRAY_SIZE(fds)) + + !!(j & 16) : 0, + j & 64 ? ", resv=0xbadc0ded" : "", + j & 128 ? ", resv2=0xfacecafebeeffeed" + : ""); + print_rsrc_data(arg_iov, iov, arg_fds, fds, + i, j, endptr, false); + print_rsrc_tags(arg_tags, tags, i, j, + arg_tags + ARRAY_SIZE(tags)); + if (!(k & 1)) + printf(", ???"); + if (k == 3) { + printf(", /* bytes 32..39 */ \"\\xa0" + "\\xa1\\xa2\\xa3\\xa4\\xa5\\xa6" + "\\xa7\""); + } + printf("}, %zu) = %s\n", + sizeof(*rsrc_reg) + (k / 2) * 8, errstr); + } + } + } + + + /* IORING_REGISTER_FILES_UPDATE2, IORING_REGISTER_BUFFERS_UPDATE */ + static const struct { + unsigned int op; + const char *str; + } rsrc_upd_ops[] = { + { 14, "IORING_REGISTER_FILES_UPDATE2" }, + { 16, "IORING_REGISTER_BUFFERS_UPDATE" }, + }; + + struct io_uring_rsrc_update2 *bogus_rsrc_upd = tail_alloc(24); + struct io_uring_rsrc_update2 *rsrc_upd = tail_alloc(sizeof(*rsrc_upd)); + struct io_uring_rsrc_update2 *big_rsrc_upd = + tail_alloc(sizeof(*big_rsrc_upd) + 8); + + fill_memory(big_rsrc_upd, sizeof(*big_rsrc_upd) + 8); + + for (size_t i = 0; i < ARRAY_SIZE(rsrc_upd_ops); i++) { + sys_io_uring_register(fd_null, rsrc_upd_ops[i].op, 0, + 0xdeadbeef); + printf("io_uring_register(%u<%s>, " XLAT_FMT ", NULL, %u)" + " = %s\n", + fd_null, path_null, + XLAT_SEL(rsrc_upd_ops[i].op, rsrc_upd_ops[i].str), + 0xdeadbeef, errstr); + + struct { + void *ptr; + unsigned int sz; + } ptr_args[] = { + { bogus_rsrc_upd, 24 }, + { bogus_rsrc_upd, 32 }, + }; + for (size_t j = 0; j < ARRAY_SIZE(ptr_args); j++) { + sys_io_uring_register(fd_null, rsrc_upd_ops[i].op, + ptr_args[j].ptr, ptr_args[j].sz); + printf("io_uring_register(%u<%s>, " XLAT_FMT ", %p, %u)" + " = %s\n", + fd_null, path_null, + XLAT_SEL(rsrc_upd_ops[i].op, + rsrc_upd_ops[i].str), + ptr_args[j].ptr, ptr_args[j].sz, errstr); + } + + for (size_t j = 0; j < 256; j++) { + void *endptr = i ? (void *) (arg_iov + ARRAY_SIZE(iov)) + : (void *) (arg_fds + ARRAY_SIZE(fds)); + + rsrc_upd->data = i ? (uintptr_t) arg_iov + : (uintptr_t) arg_fds; + rsrc_upd->nr = i ? ARRAY_SIZE(iov) : ARRAY_SIZE(fds); + rsrc_upd->tags = (uintptr_t) (arg_tags + + ARRAY_SIZE(tags) + - rsrc_upd->nr); + + rsrc_upd->data &= ~-!(j & 1); + rsrc_upd->data |= j & 2 ? BIG_ADDR_MASK : 0; + rsrc_upd->tags -= !!(j & 64) * sizeof(uint64_t); + rsrc_upd->tags &= ~-!!(j & 4); + rsrc_upd->tags |= j & 8 ? BIG_ADDR_MASK : 0; + rsrc_upd->nr += !!(j & 16); + rsrc_upd->nr &= ~-!(j & 32); + + rsrc_upd->resv = j & 64 ? 0xbadc0ded : 0; + rsrc_upd->resv2 = j & 128 ? 0xfacecafe : 0; + + rsrc_upd->offset = j % 3 ? 0 : 0xdeadface; + + memcpy(big_rsrc_upd, rsrc_upd, sizeof(*rsrc_upd)); + + for (size_t k = 1; k < 5; k++) { + sys_io_uring_register(fd_null, + rsrc_upd_ops[i].op, + k > 2 ? big_rsrc_upd + : rsrc_upd, + sizeof(*rsrc_upd) + + (k / 2) * 8); + printf("io_uring_register(%u<%s>, " XLAT_FMT + ", {offset=%s%s", + fd_null, path_null, + XLAT_SEL(rsrc_upd_ops[i].op, + rsrc_upd_ops[i].str), + j % 3 ? "0" : "3735943886", + j & 64 ? ", resv=0xbadc0ded" : ""); + print_rsrc_data(arg_iov, iov, arg_fds, fds, + i, j, endptr, true); + print_rsrc_tags(arg_tags, tags, i, j, + arg_tags + ARRAY_SIZE(tags)); + printf(", nr=%zu%s", + j & 32 ? (i ? ARRAY_SIZE(iov) + : ARRAY_SIZE(fds)) + + !!(j & 16) : 0, + j & 128 ? ", resv2=0xfacecafe" + : ""); + if (!(k & 1)) + printf(", ???"); + if (k == 3) { + printf(", /* bytes 32..39 */ \"\\xa0" + "\\xa1\\xa2\\xa3\\xa4\\xa5\\xa6" + "\\xa7\""); + } + printf("}, %zu) = %s\n", + sizeof(*rsrc_upd) + (k / 2) * 8, errstr); + } + } + } + puts("+++ exited with 0 +++"); return 0; } |