summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEugene Syromyatnikov <evgsyr@gmail.com>2022-05-02 03:50:34 +0200
committerDmitry V. Levin <ldv@strace.io>2022-05-02 01:50:34 +0000
commitdb211a06d1e028173a3fc0a0f715c91ccbd97d8a (patch)
tree0ce8da6023b0658cd0758a74a6ecafb7e859ad01
parent894b9ac409a0ef29b2a3fb6af51598a9fad9ecf6 (diff)
downloadstrace-db211a06d1e028173a3fc0a0f715c91ccbd97d8a.tar.gz
io_uring: decode IORING_{,UN}REGISTER_RING_FDS io_uring_register operations
* src/xlat/uring_register_opcodes.in (IORING_REGISTER_RING_FDS, IORING_UNREGISTER_RING_FDS): New constants, introduced by Linux commit v5.18-rc1~22^2~44. * src/io_uring.c (print_ringfd_register_array_member, print_io_uring_ringfds_register, print_ringfd_unregister_array_member, print_io_uring_ringfds_unregister): New functions. (SYS_FUNC(io_uring_register)) <case IORING_REGISTER_RING_FDS>: New case, call print_io_uring_ringfds_register. (SYS_FUNC(io_uring_register)) <case IORING_UNREGISTER_RING_FDS>: New case, call print_io_uring_ringfds_unregister. * tests/io_uring_register.c: Update expected output, add checks for IORING_REGISTER_RING_FDS and IORING_UNREGISTER_RING_FDS ops decoding. * NEWS: Mention this.
-rw-r--r--NEWS1
-rw-r--r--src/io_uring.c82
-rw-r--r--src/xlat/uring_register_opcodes.in2
-rw-r--r--tests/io_uring_register.c102
4 files changed, 184 insertions, 3 deletions
diff --git a/NEWS b/NEWS
index 719b32b64..b19eace89 100644
--- a/NEWS
+++ b/NEWS
@@ -5,6 +5,7 @@ Noteworthy changes in release ?.?? (????-??-??)
* Added an interface of raising des Strausses awareness.
* Added --tips option to print strace tips, tricks, and tweaks
at the end of the tracing session.
+ * Enhanced decoding of io_uring_register syscall.
* Updated lists of BR_*, BTRFS_*, IFA_*, IFLA_*, KEY_*, and MADV_* constants.
* Bug fixes
diff --git a/src/io_uring.c b/src/io_uring.c
index 796e374bc..be86ca41e 100644
--- a/src/io_uring.c
+++ b/src/io_uring.c
@@ -485,6 +485,82 @@ print_io_uring_iowq_acct(struct tcb *tcp, const kernel_ulong_t addr,
return ret ? 0 : RVAL_DECODED;
}
+static bool
+print_ringfd_register_array_member(struct tcb *tcp, void *buf,
+ size_t elem_size, void *data)
+{
+ /* offset - offset to insert at or -1 for the first free place */
+ /* resv - reserved */
+ /* data - FD to register */
+ struct io_uring_rsrc_update *elem = buf;
+
+ tprint_struct_begin();
+ if (elem->offset == -1U)
+ PRINT_FIELD_D(*elem, offset);
+ else
+ PRINT_FIELD_U(*elem, offset);
+
+ if (elem->resv) {
+ tprint_struct_next();
+ PRINT_FIELD_X(*elem, resv);
+ }
+
+ tprint_struct_next();
+ PRINT_FIELD_FD(*elem, data, tcp);
+
+ tprint_struct_end();
+
+ return true;
+}
+static void
+print_io_uring_ringfds_register(struct tcb *tcp, const kernel_ulong_t arg,
+ const unsigned int nargs)
+{
+ struct io_uring_rsrc_update buf;
+ CHECK_TYPE_SIZE(buf, 16);
+ CHECK_TYPE_SIZE(buf.resv, sizeof(uint32_t));
+
+ print_array(tcp, arg, nargs, &buf, sizeof(buf),
+ tfetch_mem, print_ringfd_register_array_member, NULL);
+}
+
+
+static bool
+print_ringfd_unregister_array_member(struct tcb *tcp, void *buf,
+ size_t elem_size, void *data)
+{
+ /* offset - offset to unregister FD */
+ /* resv - reserved */
+ /* data - unused */
+ struct io_uring_rsrc_update *elem = buf;
+
+ tprint_struct_begin();
+ PRINT_FIELD_U(*elem, offset);
+
+ if (elem->resv) {
+ tprint_struct_next();
+ PRINT_FIELD_X(*elem, resv);
+ }
+
+ if (elem->data) {
+ tprint_struct_next();
+ PRINT_FIELD_X(*elem, data);
+ }
+
+ tprint_struct_end();
+
+ return true;
+}
+static void
+print_io_uring_ringfds_unregister(struct tcb *tcp, const kernel_ulong_t arg,
+ const unsigned int nargs)
+{
+ struct io_uring_rsrc_update buf;
+
+ print_array(tcp, arg, nargs, &buf, sizeof(buf),
+ tfetch_mem, print_ringfd_unregister_array_member, NULL);
+}
+
SYS_FUNC(io_uring_register)
{
const int fd = tcp->u_arg[0];
@@ -541,6 +617,12 @@ SYS_FUNC(io_uring_register)
if (entering(tcp) && !rc)
tprint_value_changed();
break;
+ case IORING_REGISTER_RING_FDS:
+ print_io_uring_ringfds_register(tcp, arg, nargs);
+ break;
+ case IORING_UNREGISTER_RING_FDS:
+ print_io_uring_ringfds_unregister(tcp, arg, nargs);
+ break;
case IORING_UNREGISTER_BUFFERS:
case IORING_UNREGISTER_FILES:
case IORING_UNREGISTER_EVENTFD:
diff --git a/src/xlat/uring_register_opcodes.in b/src/xlat/uring_register_opcodes.in
index 966d8cb37..2292bdaff 100644
--- a/src/xlat/uring_register_opcodes.in
+++ b/src/xlat/uring_register_opcodes.in
@@ -20,3 +20,5 @@ IORING_REGISTER_BUFFERS_UPDATE
IORING_REGISTER_IOWQ_AFF
IORING_UNREGISTER_IOWQ_AFF
IORING_REGISTER_IOWQ_MAX_WORKERS
+IORING_REGISTER_RING_FDS
+IORING_UNREGISTER_RING_FDS
diff --git a/tests/io_uring_register.c b/tests/io_uring_register.c
index bbd703196..47311276a 100644
--- a/tests/io_uring_register.c
+++ b/tests/io_uring_register.c
@@ -152,6 +152,7 @@ main(void)
skip_if_unavailable("/proc/self/fd/");
+ close(0); /* Trying to get fd 0 for /dev/null */
int fd_null = open(path_null, O_RDONLY);
if (fd_null < 0)
perror_msg_and_fail("open: %s", path_null);
@@ -161,11 +162,12 @@ main(void)
perror_msg_and_fail("open: %s", path_full);
int fds[] = { fd_full, fd_null, -1, -2, -3 };
+ const char *paths[ARRAY_SIZE(fds)] = { path_full, path_null };
const int *arg_fds = tail_memdup(fds, sizeof(fds));
/* Invalid op */
- static const unsigned int invalid_ops[] = { 0xbadc0dedU, 20 };
+ static const unsigned int invalid_ops[] = { 0xbadc0dedU, 22 };
for (size_t i = 0; i < ARRAY_SIZE(invalid_ops); i++) {
sys_io_uring_register(fd_null, invalid_ops[i], path_null,
@@ -452,10 +454,10 @@ main(void)
{ ARG_STR(IORING_RESTRICTION_REGISTER_OP), true,
"register_op=", ARG_STR(IORING_REGISTER_BUFFERS), true },
{ ARG_STR(IORING_RESTRICTION_REGISTER_OP), true,
- "register_op=", ARG_STR(IORING_UNREGISTER_IOWQ_AFF),
+ "register_op=", ARG_STR(IORING_UNREGISTER_RING_FDS),
true },
{ ARG_STR(IORING_RESTRICTION_REGISTER_OP), true,
- "register_op=", 20, " /* IORING_REGISTER_??? */", false },
+ "register_op=", 22, " /* IORING_REGISTER_??? */", false },
{ ARG_STR(IORING_RESTRICTION_REGISTER_OP), true,
"register_op=", 255, " /* IORING_REGISTER_??? */", false },
{ ARG_STR(IORING_RESTRICTION_SQE_OP), true,
@@ -962,6 +964,100 @@ main(void)
#endif
errstr);
+
+ /* IORING_REGISTER_RING_FDS, IORING_UNREGISTER_RING_FDS */
+ static const struct {
+ unsigned int op;
+ const char *str;
+ } ringfd_ops[] = {
+ { 20, "IORING_REGISTER_RING_FDS" },
+ { 21, "IORING_UNREGISTER_RING_FDS" },
+ };
+
+ static const size_t ringfd_count = DEFAULT_STRLEN + 1;
+ static const uint32_t ringfd_off[] =
+ { -1U, 0, 1, 2, 161803398, 3141592653, -2U };
+ TAIL_ALLOC_OBJECT_VAR_ARR(struct io_uring_rsrc_update, ringfds,
+ ringfd_count);
+
+ fill_memory(ringfds, sizeof(*ringfds) * ringfd_count);
+ for (size_t i = 0; i < ringfd_count; i++) {
+ ringfds[i].offset = ringfd_off[i % ARRAY_SIZE(ringfd_off)];
+ ringfds[i].resv = i % 2 ? i * 0x1010101 : 0;
+ ringfds[i].data = (i % 4 ? 0xbadc0ded00000000ULL : 0)
+ | fds[i % ARRAY_SIZE(fds)];
+ }
+
+ for (size_t i = 0; i < ARRAY_SIZE(ringfd_ops); i++) {
+ sys_io_uring_register(fd_null, ringfd_ops[i].op, 0,
+ 0xdeadbeef);
+ printf("io_uring_register(%u<%s>, " XLAT_FMT ", NULL, %u)"
+ " = %s\n",
+ fd_null, path_null,
+ XLAT_SEL(ringfd_ops[i].op, ringfd_ops[i].str),
+ 0xdeadbeef, errstr);
+
+ sys_io_uring_register(fd_null, ringfd_ops[i].op,
+ ringfds + ringfd_count, 0);
+ printf("io_uring_register(%u<%s>, " XLAT_FMT ", [], 0) = %s\n",
+ fd_null, path_null,
+ XLAT_SEL(ringfd_ops[i].op, ringfd_ops[i].str),
+ errstr);
+
+ sys_io_uring_register(fd_null, ringfd_ops[i].op,
+ ringfds + ringfd_count, 1);
+ printf("io_uring_register(%u<%s>, " XLAT_FMT ", %p, 1)"
+ " = %s\n",
+ fd_null, path_null,
+ XLAT_SEL(ringfd_ops[i].op, ringfd_ops[i].str),
+ ringfds + ringfd_count, errstr);
+
+ /* offs:sz: 33-31:32, 33-32:32, 33-32:33, 33-33:33 */
+ for (size_t j = 0; j < 4; j++) {
+ const size_t offs = (4 - j) / 2;
+ const size_t sz = 32 + j / 2;
+
+ sys_io_uring_register(fd_null, ringfd_ops[i].op,
+ ringfds + offs, sz);
+ printf("io_uring_register(%u<%s>, " XLAT_FMT ", [",
+ fd_null, path_null,
+ XLAT_SEL(ringfd_ops[i].op, ringfd_ops[i].str));
+ for (uint32_t k = offs; k < MIN(ringfd_count,
+ DEFAULT_STRLEN + offs);
+ k++) {
+ printf("%s{offset=", k != offs ? ", " : "");
+ printf(ringfd_ops[i].op == 21 ||
+ k % ARRAY_SIZE(ringfd_off) ? "%u" : "%d",
+ ringfd_off[k % ARRAY_SIZE(ringfd_off)]);
+ if (k % 2)
+ printf(", resv=%#x", k * 0x1010101);
+
+ const size_t fdid = k % ARRAY_SIZE(fds);
+ if (ringfd_ops[i].op == 20) {
+ printf(", data=%d%s%s%s",
+ fds[fdid],
+ paths[fdid] ? "<": "",
+ paths[fdid] ? paths[fdid] : "",
+ paths[fdid] ? ">": "");
+ } else {
+ if (!((k % ARRAY_SIZE(fds) == 1)
+ && !(k % 4))) {
+ printf(", data=%#llx",
+ (k % 4
+ ? 0xbadc0ded00000000ULL
+ : 0) | fds[fdid]);
+ }
+ }
+ printf("}");
+ }
+ if (j != 1)
+ printf(", ...");
+ if (!(j % 2))
+ printf(" /* %p */", ringfds + ringfd_count);
+ printf("], %zu) = %s\n", sz, errstr);
+ }
+ }
+
puts("+++ exited with 0 +++");
return 0;
}