summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEugene Syromyatnikov <evgsyr@gmail.com>2021-09-17 19:25:47 +0200
committerEugene Syromyatnikov <evgsyr@gmail.com>2021-10-12 00:35:30 +0200
commit941792d08da6917c63243775be35429a21c2b36c (patch)
tree55d815c69c18f512b03eb85ed7f49f7c4e429a31
parent0cf482530a95d6034b6987333fdd334dcd58308f (diff)
downloadstrace-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.c141
-rw-r--r--tests/io_uring_register.c291
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;
}