diff options
author | Dmitry V. Levin <ldv@altlinux.org> | 2019-05-19 23:35:20 +0000 |
---|---|---|
committer | Dmitry V. Levin <ldv@altlinux.org> | 2019-05-19 23:35:20 +0000 |
commit | d7e00d657a1f623d5f794827e4bfe6db1abaad34 (patch) | |
tree | 38817572854b0844b05ad3e4787934ccaec26005 | |
parent | f625d610c7018cef0380f81e513695c66615443c (diff) | |
download | strace-d7e00d657a1f623d5f794827e4bfe6db1abaad34.tar.gz |
Implement decoding of io_uring_* syscalls
... introduced by Linux kernel commits v5.1-rc1~99^2~14,
v5.1-rc1~99^2~7, and v5.1-rc7~24^2.
* configure.ac (AC_CHECK_HEADERS): Add linux/io_uring.h.
* io_uring.c: New file.
* Makefile.am (strace_SOURCES): Add it.
* pathtrace.c (pathtrace_match_set): Add SEN_io_uring_enter,
SEN_io_uring_register, and SEN_io_uring_setup.
* xlat/uring_enter_flags.in: New file.
* xlat/uring_register_opcodes.in: Likewise.
* linux/32/syscallent.h [425, 426, 427]: Wire up io_uring_setup,
io_uring_enter, and io_uring_register.
* linux/64/syscallent.h: Likewise.
* linux/arm/syscallent.h: Likewise.
* linux/hppa/syscallent.h: Likewise.
* linux/i386/syscallent.h: Likewise.
* linux/m68k/syscallent.h: Likewise.
* linux/microblaze/syscallent.h: Likewise.
* linux/powerpc/syscallent.h: Likewise.
* linux/powerpc64/syscallent.h: Likewise.
* linux/s390/syscallent.h: Likewise.
* linux/s390x/syscallent.h: Likewise.
* linux/sh/syscallent.h: Likewise.
* linux/sh64/syscallent.h: Likewise.
* linux/sparc/syscallent.h: Likewise.
* linux/sparc64/syscallent.h: Likewise.
* linux/x32/syscallent.h: Likewise.
* linux/x86_64/syscallent.h: Likewise.
* linux/xtensa/syscallent.h: Likewise.
* linux/alpha/syscallent.h [535, 536, 537]: Likewise.
* linux/ia64/syscallent.h [1024 + 425, 1024 + 426, 1024 + 427]: Likewise.
* linux/mips/syscallent-n32.h [6425, 6426, 6427]: Likewise.
* linux/mips/syscallent-n64.h [5425, 5426, 5427]: Likewise.
* linux/mips/syscallent-o32.h [4425, 4426, 4427]: Likewise.
* NEWS: Mention this change.
* tests/io_uring_enter.c: New file.
* tests/io_uring_register.c: Likewise.
* tests/io_uring_setup.c: Likewise.
* tests/gen_tests.in (io_uring_enter, io_uring_register,
io_uring_setup): New entries.
* tests/pure_executables.list: Add io_uring_enter, io_uring_register,
and io_uring_setup.
* tests/.gitignore: Likewise.
37 files changed, 515 insertions, 1 deletions
diff --git a/Makefile.am b/Makefile.am index ef42de72d..a8ace321d 100644 --- a/Makefile.am +++ b/Makefile.am @@ -145,6 +145,7 @@ strace_SOURCES = \ inotify.c \ inotify_ioctl.c \ io.c \ + io_uring.c \ ioctl.c \ ioperm.c \ iopl.c \ @@ -13,7 +13,8 @@ Noteworthy changes in release ?.? (????-??-??) pselect6_time64, ppoll_time64, io_pgetevents_time64, recvmmsg_time64, mq_timedsend_time64, mq_timedreceive_time64, semtimedop_time64, rt_sigtimedwait_time64, futex_time64, sched_rr_get_interval_time64, - and pidfd_send_signal syscalls. + pidfd_send_signal, io_uring_setup, io_uring_enter, and io_uring_register + syscalls. * Wired up getegid, geteuid, getppid, io_pgetevents, statfs64, and fstatfs64 syscalls on alpha. * Wired up kexec_file_load and migrate_pages syscalls on arm. diff --git a/configure.ac b/configure.ac index e7df4fe60..621312ac4 100644 --- a/configure.ac +++ b/configure.ac @@ -387,6 +387,7 @@ AC_CHECK_HEADERS(m4_normalize([ linux/hiddev.h linux/if_addr.h linux/if_link.h + linux/io_uring.h linux/ip_vs.h linux/ipc.h linux/kcmp.h diff --git a/io_uring.c b/io_uring.c new file mode 100644 index 000000000..0b82a0754 --- /dev/null +++ b/io_uring.c @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2019 Dmitry V. Levin <ldv@altlinux.org> + * All rights reserved. + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +#include "defs.h" + +#ifdef HAVE_LINUX_IO_URING_H +# include "print_fields.h" +# include <linux/io_uring.h> +#endif + +#include "xlat/uring_setup_flags.h" +#include "xlat/uring_enter_flags.h" +#include "xlat/uring_register_opcodes.h" + +SYS_FUNC(io_uring_setup) +{ + const uint32_t nentries = tcp->u_arg[0]; + const kernel_ulong_t params_addr = tcp->u_arg[1]; + +#ifdef HAVE_LINUX_IO_URING_H + struct io_uring_params params; + + if (entering(tcp)) { + tprintf("%u, ", nentries); + + if (umove_or_printaddr(tcp, params_addr, ¶ms)) + return RVAL_DECODED | RVAL_FD; + + PRINT_FIELD_FLAGS("{", params, flags, uring_setup_flags, + "IORING_SETUP_???"); + PRINT_FIELD_X(", ", params, sq_thread_cpu); + PRINT_FIELD_U(", ", params, sq_thread_idle); + for (unsigned int i = 0; i < ARRAY_SIZE(params.resv); ++i) { + if (params.resv[i]) { + for (i = 0; i < ARRAY_SIZE(params.resv); ++i) + tprintf("%s%#x", + (i ? ", " : ", resv={"), + params.resv[i]); + tprints("}"); + break; + } + } + return 0; + } else { + if (syserror(tcp)) { + /* The remaining part of params is irrelevant. */ + } else if (umove(tcp, params_addr, ¶ms)) { + tprints(", ???"); + } else { + PRINT_FIELD_U(", ", params, sq_entries); + PRINT_FIELD_U(", ", params, cq_entries); + PRINT_FIELD_U(", sq_off={", params.sq_off, head); + PRINT_FIELD_U(", ", params.sq_off, tail); + PRINT_FIELD_U(", ", params.sq_off, ring_mask); + PRINT_FIELD_U(", ", params.sq_off, ring_entries); + PRINT_FIELD_U(", ", params.sq_off, flags); + PRINT_FIELD_U(", ", params.sq_off, dropped); + PRINT_FIELD_U(", ", params.sq_off, array); + PRINT_FIELD_U("}, cq_off={", params.cq_off, head); + PRINT_FIELD_U(", ", params.cq_off, tail); + PRINT_FIELD_U(", ", params.cq_off, ring_mask); + PRINT_FIELD_U(", ", params.cq_off, ring_entries); + PRINT_FIELD_U(", ", params.cq_off, overflow); + PRINT_FIELD_U(", ", params.cq_off, cqes); + tprints("}"); + } + tprints("}"); + } +#else /* !HAVE_LINUX_IO_URING_H */ + tprintf("%u, ", nentries); + printaddr(params_addr); +#endif + + return RVAL_DECODED | RVAL_FD; +} + +SYS_FUNC(io_uring_enter) +{ + const int fd = tcp->u_arg[0]; + const uint32_t to_submit = tcp->u_arg[1]; + const uint32_t min_complete = tcp->u_arg[2]; + const uint32_t flags = tcp->u_arg[3]; + const kernel_ulong_t sigset_addr = tcp->u_arg[4]; + const kernel_ulong_t sigset_size = tcp->u_arg[5]; + + printfd(tcp, fd); + tprintf(", %u, %u, ", to_submit, min_complete); + printflags(uring_enter_flags, flags, "IORING_ENTER_???"); + tprints(", "); + print_sigset_addr_len(tcp, sigset_addr, sigset_size); + tprintf(", %" PRI_klu, sigset_size); + + return RVAL_DECODED; +} + +static bool +print_fd_array_member(struct tcb *tcp, void *elem_buf, size_t elem_size, + void *data) +{ + printfd(tcp, *(int *) elem_buf); + return true; +} + +SYS_FUNC(io_uring_register) +{ + const int fd = tcp->u_arg[0]; + const unsigned int opcode = tcp->u_arg[1]; + const kernel_ulong_t arg = tcp->u_arg[2]; + const unsigned int nargs = tcp->u_arg[3]; + int buf; + + printfd(tcp, fd); + tprints(", "); + printxval(uring_register_opcodes, opcode, "IORING_REGISTER_???"); + tprints(", "); + switch (opcode) { + case IORING_REGISTER_BUFFERS: + tprint_iov(tcp, nargs, arg, IOV_DECODE_ADDR); + break; + case IORING_REGISTER_FILES: + print_array(tcp, arg, nargs, &buf, sizeof(buf), + tfetch_mem, print_fd_array_member, NULL); + break; + default: + printaddr(arg); + break; + } + tprintf(", %u", nargs); + + return RVAL_DECODED; +} diff --git a/linux/32/syscallent.h b/linux/32/syscallent.h index 0d78f42e9..01a5009df 100644 --- a/linux/32/syscallent.h +++ b/linux/32/syscallent.h @@ -313,6 +313,9 @@ [422] = { 6, 0, SEN(futex_time64), "futex_time64" }, [423] = { 2, 0, SEN(sched_rr_get_interval_time64), "sched_rr_get_interval_time64" }, [424] = { 4, TD|TS, SEN(pidfd_send_signal), "pidfd_send_signal" }, +[425] = { 2, TD, SEN(io_uring_setup), "io_uring_setup" }, +[426] = { 6, TD|TS, SEN(io_uring_enter), "io_uring_enter" }, +[427] = { 4, TD|TM, SEN(io_uring_register), "io_uring_register" }, #undef sys_ARCH_mmap #undef ARCH_WANT_SYNC_FILE_RANGE2 diff --git a/linux/64/syscallent.h b/linux/64/syscallent.h index 7188f73bd..294da6901 100644 --- a/linux/64/syscallent.h +++ b/linux/64/syscallent.h @@ -287,3 +287,6 @@ [294] = { 5, TD, SEN(kexec_file_load), "kexec_file_load" }, /* [295 ... 423] - reserved to sync up with other architectures */ [424] = { 4, TD|TS, SEN(pidfd_send_signal), "pidfd_send_signal" }, +[425] = { 2, TD, SEN(io_uring_setup), "io_uring_setup" }, +[426] = { 6, TD|TS, SEN(io_uring_enter), "io_uring_enter" }, +[427] = { 4, TD|TM, SEN(io_uring_register), "io_uring_register" }, diff --git a/linux/alpha/syscallent.h b/linux/alpha/syscallent.h index c78a120a0..7fa8f1469 100644 --- a/linux/alpha/syscallent.h +++ b/linux/alpha/syscallent.h @@ -478,3 +478,6 @@ [532] = { 0, PU|NF, SEN(getppid), "getppid" }, /* all other architectures have common numbers for new syscalls, alpha is the exception */ [534] = { 4, TD|TS, SEN(pidfd_send_signal), "pidfd_send_signal" }, +[535] = { 2, TD, SEN(io_uring_setup), "io_uring_setup" }, +[536] = { 6, TD|TS, SEN(io_uring_enter), "io_uring_enter" }, +[537] = { 4, TD|TM, SEN(io_uring_register), "io_uring_register" }, diff --git a/linux/arm/syscallent.h b/linux/arm/syscallent.h index 73d29eff2..8f85a4957 100644 --- a/linux/arm/syscallent.h +++ b/linux/arm/syscallent.h @@ -431,6 +431,9 @@ [422] = { 6, 0, SEN(futex_time64), "futex_time64" }, [423] = { 2, 0, SEN(sched_rr_get_interval_time64), "sched_rr_get_interval_time64" }, [424] = { 4, TD|TS, SEN(pidfd_send_signal), "pidfd_send_signal" }, +[425] = { 2, TD, SEN(io_uring_setup), "io_uring_setup" }, +[426] = { 6, TD|TS, SEN(io_uring_enter), "io_uring_enter" }, +[427] = { 4, TD|TM, SEN(io_uring_register), "io_uring_register" }, #ifdef __ARM_EABI__ # define ARM_FIRST_SHUFFLED_SYSCALL 500 diff --git a/linux/hppa/syscallent.h b/linux/hppa/syscallent.h index 56f5682be..1a62ad31e 100644 --- a/linux/hppa/syscallent.h +++ b/linux/hppa/syscallent.h @@ -380,3 +380,6 @@ [422] = { 6, 0, SEN(futex_time64), "futex_time64" }, [423] = { 2, 0, SEN(sched_rr_get_interval_time64), "sched_rr_get_interval_time64" }, [424] = { 4, TD|TS, SEN(pidfd_send_signal), "pidfd_send_signal" }, +[425] = { 2, TD, SEN(io_uring_setup), "io_uring_setup" }, +[426] = { 6, TD|TS, SEN(io_uring_enter), "io_uring_enter" }, +[427] = { 4, TD|TM, SEN(io_uring_register), "io_uring_register" }, diff --git a/linux/i386/syscallent.h b/linux/i386/syscallent.h index fee1cddf8..98866f3da 100644 --- a/linux/i386/syscallent.h +++ b/linux/i386/syscallent.h @@ -425,6 +425,9 @@ [422] = { 6, 0, SEN(futex_time64), "futex_time64" }, [423] = { 2, 0, SEN(sched_rr_get_interval_time64), "sched_rr_get_interval_time64" }, [424] = { 4, TD|TS, SEN(pidfd_send_signal), "pidfd_send_signal" }, +[425] = { 2, TD, SEN(io_uring_setup), "io_uring_setup" }, +[426] = { 6, TD|TS, SEN(io_uring_enter), "io_uring_enter" }, +[427] = { 4, TD|TM, SEN(io_uring_register), "io_uring_register" }, #define SYS_socket_subcall 500 #include "subcall32.h" diff --git a/linux/ia64/syscallent.h b/linux/ia64/syscallent.h index 1e3934be5..3ec6dabd7 100644 --- a/linux/ia64/syscallent.h +++ b/linux/ia64/syscallent.h @@ -343,3 +343,6 @@ [1024 + 333] = { 4, 0, SEN(rseq), "rseq" }, /* [1024 + 334 ... 1024 + 423] - reserved to sync up with other architectures */ [1024 + 424] = { 4, TD|TS, SEN(pidfd_send_signal), "pidfd_send_signal" }, +[1024 + 425] = { 2, TD, SEN(io_uring_setup), "io_uring_setup" }, +[1024 + 426] = { 6, TD|TS, SEN(io_uring_enter), "io_uring_enter" }, +[1024 + 427] = { 4, TD|TM, SEN(io_uring_register), "io_uring_register" }, diff --git a/linux/m68k/syscallent.h b/linux/m68k/syscallent.h index c35b0765e..f21176975 100644 --- a/linux/m68k/syscallent.h +++ b/linux/m68k/syscallent.h @@ -423,6 +423,9 @@ [422] = { 6, 0, SEN(futex_time64), "futex_time64" }, [423] = { 2, 0, SEN(sched_rr_get_interval_time64), "sched_rr_get_interval_time64" }, [424] = { 4, TD|TS, SEN(pidfd_send_signal), "pidfd_send_signal" }, +[425] = { 2, TD, SEN(io_uring_setup), "io_uring_setup" }, +[426] = { 6, TD|TS, SEN(io_uring_enter), "io_uring_enter" }, +[427] = { 4, TD|TM, SEN(io_uring_register), "io_uring_register" }, #define SYS_socket_subcall 500 #include "subcall32.h" diff --git a/linux/microblaze/syscallent.h b/linux/microblaze/syscallent.h index aeda7b84e..9feefac54 100644 --- a/linux/microblaze/syscallent.h +++ b/linux/microblaze/syscallent.h @@ -429,3 +429,6 @@ [422] = { 6, 0, SEN(futex_time64), "futex_time64" }, [423] = { 2, 0, SEN(sched_rr_get_interval_time64), "sched_rr_get_interval_time64" }, [424] = { 4, TD|TS, SEN(pidfd_send_signal), "pidfd_send_signal" }, +[425] = { 2, TD, SEN(io_uring_setup), "io_uring_setup" }, +[426] = { 6, TD|TS, SEN(io_uring_enter), "io_uring_enter" }, +[427] = { 4, TD|TM, SEN(io_uring_register), "io_uring_register" }, diff --git a/linux/mips/syscallent-n32.h b/linux/mips/syscallent-n32.h index e9c5e5d23..16ec2a1bd 100644 --- a/linux/mips/syscallent-n32.h +++ b/linux/mips/syscallent-n32.h @@ -362,6 +362,9 @@ [6422] = { 6, 0, SEN(futex_time64), "futex_time64" }, [6423] = { 2, 0, SEN(sched_rr_get_interval_time64), "sched_rr_get_interval_time64" }, [6424] = { 4, TD|TS, SEN(pidfd_send_signal), "pidfd_send_signal" }, +[6425] = { 2, TD, SEN(io_uring_setup), "io_uring_setup" }, +[6426] = { 6, TD|TS, SEN(io_uring_enter), "io_uring_enter" }, +[6427] = { 4, TD|TM, SEN(io_uring_register), "io_uring_register" }, # define SYS_socket_subcall 6500 # include "subcall32.h" diff --git a/linux/mips/syscallent-n64.h b/linux/mips/syscallent-n64.h index f2bb30c52..15db301ee 100644 --- a/linux/mips/syscallent-n64.h +++ b/linux/mips/syscallent-n64.h @@ -338,6 +338,9 @@ [5328] = { 6, 0, SEN(io_pgetevents_time64), "io_pgetevents" }, /* [5329 ... 5423] - reserved to sync up with other architectures */ [5424] = { 4, TD|TS, SEN(pidfd_send_signal), "pidfd_send_signal" }, +[5425] = { 2, TD, SEN(io_uring_setup), "io_uring_setup" }, +[5426] = { 6, TD|TS, SEN(io_uring_enter), "io_uring_enter" }, +[5427] = { 4, TD|TM, SEN(io_uring_register), "io_uring_register" }, # define SYS_socket_subcall 5500 # include "subcall64.h" diff --git a/linux/mips/syscallent-o32.h b/linux/mips/syscallent-o32.h index 9cd3b1d0c..7fdc60f67 100644 --- a/linux/mips/syscallent-o32.h +++ b/linux/mips/syscallent-o32.h @@ -409,6 +409,9 @@ [4422] = { 6, 0, SEN(futex_time64), "futex_time64" }, [4423] = { 2, 0, SEN(sched_rr_get_interval_time64), "sched_rr_get_interval_time64" }, [4424] = { 4, TD|TS, SEN(pidfd_send_signal), "pidfd_send_signal" }, +[4425] = { 2, TD, SEN(io_uring_setup), "io_uring_setup" }, +[4426] = { 6, TD|TS, SEN(io_uring_enter), "io_uring_enter" }, +[4427] = { 4, TD|TM, SEN(io_uring_register), "io_uring_register" }, # define SYS_socket_subcall 4500 # include "subcall32.h" diff --git a/linux/powerpc/syscallent.h b/linux/powerpc/syscallent.h index ecda494c2..4e184646b 100644 --- a/linux/powerpc/syscallent.h +++ b/linux/powerpc/syscallent.h @@ -417,6 +417,9 @@ [422] = { 6, 0, SEN(futex_time64), "futex_time64" }, [423] = { 2, 0, SEN(sched_rr_get_interval_time64), "sched_rr_get_interval_time64" }, [424] = { 4, TD|TS, SEN(pidfd_send_signal), "pidfd_send_signal" }, +[425] = { 2, TD, SEN(io_uring_setup), "io_uring_setup" }, +[426] = { 6, TD|TS, SEN(io_uring_enter), "io_uring_enter" }, +[427] = { 4, TD|TM, SEN(io_uring_register), "io_uring_register" }, #define SYS_socket_subcall 500 #include "subcall32.h" diff --git a/linux/powerpc64/syscallent.h b/linux/powerpc64/syscallent.h index 3352b346e..47a599900 100644 --- a/linux/powerpc64/syscallent.h +++ b/linux/powerpc64/syscallent.h @@ -394,6 +394,9 @@ [402] = { 3, TI, SEN(msgctl), "msgctl" }, /* [403 ... 423] - reserved to sync up with other architectures */ [424] = { 4, TD|TS, SEN(pidfd_send_signal), "pidfd_send_signal" }, +[425] = { 2, TD, SEN(io_uring_setup), "io_uring_setup" }, +[426] = { 6, TD|TS, SEN(io_uring_enter), "io_uring_enter" }, +[427] = { 4, TD|TM, SEN(io_uring_register), "io_uring_register" }, #define SYS_socket_subcall 500 #include "subcall64.h" diff --git a/linux/s390/syscallent.h b/linux/s390/syscallent.h index 8eaeae737..24cd190b7 100644 --- a/linux/s390/syscallent.h +++ b/linux/s390/syscallent.h @@ -428,6 +428,9 @@ [422] = { 6, 0, SEN(futex_time64), "futex_time64" }, [423] = { 2, 0, SEN(sched_rr_get_interval_time64), "sched_rr_get_interval_time64" }, [424] = { 4, TD|TS, SEN(pidfd_send_signal), "pidfd_send_signal" }, +[425] = { 2, TD, SEN(io_uring_setup), "io_uring_setup" }, +[426] = { 6, TD|TS, SEN(io_uring_enter), "io_uring_enter" }, +[427] = { 4, TD|TM, SEN(io_uring_register), "io_uring_register" }, #define SYS_socket_subcall 500 #include "subcall32.h" diff --git a/linux/s390x/syscallent.h b/linux/s390x/syscallent.h index 3cf61144c..5b61cdc28 100644 --- a/linux/s390x/syscallent.h +++ b/linux/s390x/syscallent.h @@ -394,6 +394,9 @@ [402] = { 3, TI, SEN(msgctl), "msgctl" }, /* [403 ... 423] - reserved to sync up with other architectures */ [424] = { 4, TD|TS, SEN(pidfd_send_signal), "pidfd_send_signal" }, +[425] = { 2, TD, SEN(io_uring_setup), "io_uring_setup" }, +[426] = { 6, TD|TS, SEN(io_uring_enter), "io_uring_enter" }, +[427] = { 4, TD|TM, SEN(io_uring_register), "io_uring_register" }, #define SYS_socket_subcall 500 #include "subcall64.h" diff --git a/linux/sh/syscallent.h b/linux/sh/syscallent.h index b14d7ed1a..44cc9d90c 100644 --- a/linux/sh/syscallent.h +++ b/linux/sh/syscallent.h @@ -426,6 +426,9 @@ [422] = { 6, 0, SEN(futex_time64), "futex_time64" }, [423] = { 2, 0, SEN(sched_rr_get_interval_time64), "sched_rr_get_interval_time64" }, [424] = { 4, TD|TS, SEN(pidfd_send_signal), "pidfd_send_signal" }, +[425] = { 2, TD, SEN(io_uring_setup), "io_uring_setup" }, +[426] = { 6, TD|TS, SEN(io_uring_enter), "io_uring_enter" }, +[427] = { 4, TD|TM, SEN(io_uring_register), "io_uring_register" }, #define SYS_socket_subcall 500 #include "subcall32.h" diff --git a/linux/sh64/syscallent.h b/linux/sh64/syscallent.h index 8a068ce5c..a21b0c47d 100644 --- a/linux/sh64/syscallent.h +++ b/linux/sh64/syscallent.h @@ -400,6 +400,9 @@ [393] = { 6, TD, SEN(pwritev2), "pwritev2" }, /* [403 ... 423] - reserved to sync up with other architectures */ [424] = { 4, TD|TS, SEN(pidfd_send_signal), "pidfd_send_signal" }, +[425] = { 2, TD, SEN(io_uring_setup), "io_uring_setup" }, +[426] = { 6, TD|TS, SEN(io_uring_enter), "io_uring_enter" }, +[427] = { 4, TD|TM, SEN(io_uring_register), "io_uring_register" }, #define SYS_socket_subcall 500 #include "subcall64.h" diff --git a/linux/sparc/syscallent.h b/linux/sparc/syscallent.h index 19900af32..706c15e6e 100644 --- a/linux/sparc/syscallent.h +++ b/linux/sparc/syscallent.h @@ -403,6 +403,9 @@ [422] = { 6, 0, SEN(futex_time64), "futex_time64" }, [423] = { 2, 0, SEN(sched_rr_get_interval_time64), "sched_rr_get_interval_time64" }, [424] = { 4, TD|TS, SEN(pidfd_send_signal), "pidfd_send_signal" }, +[425] = { 2, TD, SEN(io_uring_setup), "io_uring_setup" }, +[426] = { 6, TD|TS, SEN(io_uring_enter), "io_uring_enter" }, +[427] = { 4, TD|TM, SEN(io_uring_register), "io_uring_register" }, #define SYS_socket_subcall 500 #include "subcall32.h" diff --git a/linux/sparc64/syscallent.h b/linux/sparc64/syscallent.h index 1ed0dc234..1023b07df 100644 --- a/linux/sparc64/syscallent.h +++ b/linux/sparc64/syscallent.h @@ -383,6 +383,9 @@ [402] = { 3, TI, SEN(msgctl), "msgctl" }, /* [403 ... 423] - reserved to sync up with other architectures */ [424] = { 4, TD|TS, SEN(pidfd_send_signal), "pidfd_send_signal" }, +[425] = { 2, TD, SEN(io_uring_setup), "io_uring_setup" }, +[426] = { 6, TD|TS, SEN(io_uring_enter), "io_uring_enter" }, +[427] = { 4, TD|TM, SEN(io_uring_register), "io_uring_register" }, #define SYS_socket_subcall 500 #include "subcall64.h" diff --git a/linux/x32/syscallent.h b/linux/x32/syscallent.h index d0f8e8db0..6a9303725 100644 --- a/linux/x32/syscallent.h +++ b/linux/x32/syscallent.h @@ -382,3 +382,6 @@ [545] = { 5, CST|TD|TF|TP|SE|SI, SEN(execveat), "execveat" }, [546] = { 5, TD, SEN(preadv2), "preadv2" }, [547] = { 5, TD, SEN(pwritev2), "pwritev2" }, +[425] = { 2, TD, SEN(io_uring_setup), "io_uring_setup" }, +[426] = { 6, TD|TS, SEN(io_uring_enter), "io_uring_enter" }, +[427] = { 4, TD|TM, SEN(io_uring_register), "io_uring_register" }, diff --git a/linux/x86_64/syscallent.h b/linux/x86_64/syscallent.h index 2ac8dc6c1..41b7796f0 100644 --- a/linux/x86_64/syscallent.h +++ b/linux/x86_64/syscallent.h @@ -342,3 +342,6 @@ [334] = { 4, 0, SEN(rseq), "rseq" }, /* [335 ... 423] - reserved to sync up with other architectures */ [424] = { 4, TD|TS, SEN(pidfd_send_signal), "pidfd_send_signal" }, +[425] = { 2, TD, SEN(io_uring_setup), "io_uring_setup" }, +[426] = { 6, TD|TS, SEN(io_uring_enter), "io_uring_enter" }, +[427] = { 4, TD|TM, SEN(io_uring_register), "io_uring_register" }, diff --git a/linux/xtensa/syscallent.h b/linux/xtensa/syscallent.h index 6d0925710..79fb8d13e 100644 --- a/linux/xtensa/syscallent.h +++ b/linux/xtensa/syscallent.h @@ -370,3 +370,6 @@ [422] = { 6, 0, SEN(futex_time64), "futex_time64" }, [423] = { 2, 0, SEN(sched_rr_get_interval_time64), "sched_rr_get_interval_time64" }, [424] = { 4, TD|TS, SEN(pidfd_send_signal), "pidfd_send_signal" }, +[425] = { 2, TD, SEN(io_uring_setup), "io_uring_setup" }, +[426] = { 6, TD|TS, SEN(io_uring_enter), "io_uring_enter" }, +[427] = { 4, TD|TM, SEN(io_uring_register), "io_uring_register" }, diff --git a/pathtrace.c b/pathtrace.c index a1716caec..142e1b659 100644 --- a/pathtrace.c +++ b/pathtrace.c @@ -326,6 +326,9 @@ pathtrace_match_set(struct tcb *tcp, struct path_set *set) case SEN_fanotify_init: case SEN_inotify_init: case SEN_inotify_init1: + case SEN_io_uring_enter: + case SEN_io_uring_register: + case SEN_io_uring_setup: case SEN_memfd_create: case SEN_mq_getsetattr: case SEN_mq_notify: diff --git a/tests/.gitignore b/tests/.gitignore index 40380ac6e..fb3fa928f 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -143,6 +143,9 @@ inject-nf inotify inotify_init1 int_0x80 +io_uring_enter +io_uring_register +io_uring_setup ioctl ioctl_block ioctl_dm diff --git a/tests/gen_tests.in b/tests/gen_tests.in index b81e67d02..487b9608a 100644 --- a/tests/gen_tests.in +++ b/tests/gen_tests.in @@ -118,6 +118,9 @@ inet-cmsg -e trace=recvmsg init_module -a27 inotify -a23 -e trace=inotify_add_watch,inotify_rm_watch inotify_init1 -a27 +io_uring_enter -y +io_uring_register -y +io_uring_setup -a26 -y ioctl_block +ioctl.test ioctl_dm +ioctl.test -s9 ioctl_dm-v +ioctl.test -v -s9 diff --git a/tests/io_uring_enter.c b/tests/io_uring_enter.c new file mode 100644 index 000000000..3284ebac3 --- /dev/null +++ b/tests/io_uring_enter.c @@ -0,0 +1,83 @@ +/* + * Check decoding of io_uring_enter syscall. + * + * Copyright (c) 2019 Dmitry V. Levin <ldv@altlinux.org> + * All rights reserved. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "tests.h" +#include <unistd.h> +#include <asm/unistd.h> +#include "scno.h" + +#ifdef __NR_io_uring_enter + +# include <fcntl.h> +# include <signal.h> +# include <stdio.h> +# include <string.h> + +static const char *errstr; + +static long +sys_io_uring_enter(unsigned int fd, unsigned int to_submit, + unsigned int min_complete, unsigned int flags, + const void *sigset_addr, kernel_ulong_t sigset_size) + +{ + kernel_ulong_t fill = (kernel_ulong_t) 0xdefaced00000000ULL; + kernel_ulong_t arg1 = fill | fd; + kernel_ulong_t arg2 = fill | to_submit; + kernel_ulong_t arg3 = fill | min_complete; + kernel_ulong_t arg4 = fill | flags; + kernel_ulong_t arg5 = (unsigned long) sigset_addr; + kernel_ulong_t arg6 = sigset_size; + + long rc = syscall(__NR_io_uring_enter, + arg1, arg2, arg3, arg4, arg5, arg6); + errstr = sprintrc(rc); + return rc; +} + +int +main(void) +{ + static const char path[] = "/dev/null"; + + skip_if_unavailable("/proc/self/fd/"); + + int fd = open(path, O_RDONLY); + if (fd < 0) + perror_msg_and_fail("open: %s", path); + + const unsigned int size = get_sigset_size(); + void *const sigmask = tail_alloc(size); + sigset_t mask; + + memset(&mask, -1, sizeof(mask)); + sigdelset(&mask, SIGHUP); + sigdelset(&mask, SIGKILL); + sigdelset(&mask, SIGSTOP); + memcpy(sigmask, &mask, size); + + const unsigned int to_submit = 0xdeadbeef; + const unsigned int min_complete = 0xcafef00d; + + sys_io_uring_enter(fd, to_submit, min_complete, -1U, sigmask, size); + printf("io_uring_enter(%u<%s>, %u, %u" + ", IORING_ENTER_GETEVENTS|IORING_ENTER_SQ_WAKEUP|%#x" + ", %s, %u) = %s\n", + fd, path, to_submit, min_complete, -1U - 3, + "~[HUP KILL STOP]", size, errstr); + + puts("+++ exited with 0 +++"); + return 0; +} + +#else + +SKIP_MAIN_UNDEFINED("__NR_io_uring_enter") + +#endif diff --git a/tests/io_uring_register.c b/tests/io_uring_register.c new file mode 100644 index 000000000..a0327ed85 --- /dev/null +++ b/tests/io_uring_register.c @@ -0,0 +1,100 @@ +/* + * Check decoding of io_uring_register syscall. + * + * Copyright (c) 2019 Dmitry V. Levin <ldv@altlinux.org> + * All rights reserved. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "tests.h" +#include <unistd.h> +#include <asm/unistd.h> +#include "scno.h" + +#ifdef __NR_io_uring_register + +# include <fcntl.h> +# include <stdio.h> +# include <string.h> +# include <sys/uio.h> + +static const char *errstr; + +static long +sys_io_uring_register(unsigned int fd, unsigned int opcode, + const void *arg, unsigned int nargs) + +{ + kernel_ulong_t fill = (kernel_ulong_t) 0xdefaced00000000ULL; + kernel_ulong_t bad = (kernel_ulong_t) 0xbadc0dedbadc0dedULL; + kernel_ulong_t arg1 = fill | fd; + kernel_ulong_t arg2 = fill | opcode; + kernel_ulong_t arg3 = (unsigned long) arg; + kernel_ulong_t arg4 = fill | nargs; + + long rc = syscall(__NR_io_uring_register, + arg1, arg2, arg3, arg4, bad, bad); + errstr = sprintrc(rc); + return rc; +} + +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, + .iov_len = (unsigned long) 0xdeadfacebeefcafe + }, + { + .iov_base = (void *) path_null, + .iov_len = sizeof(path_null) + } + }; + const struct iovec *arg_iov = tail_memdup(iov, sizeof(iov)); + + skip_if_unavailable("/proc/self/fd/"); + + int fd_null = open(path_null, O_RDONLY); + if (fd_null < 0) + perror_msg_and_fail("open: %s", path_null); + + int fd_full = open(path_full, O_RDONLY); + if (fd_full < 0) + perror_msg_and_fail("open: %s", path_null); + + int fds[] = { fd_full, fd_null }; + const int *arg_fds = tail_memdup(fds, sizeof(fds)); + + sys_io_uring_register(fd_null, 0xbadc0ded, path_null, 0xdeadbeef); + printf("io_uring_register(%u<%s>, %#x /* IORING_REGISTER_??? */" + ", %p, %u) = %s\n", + fd_null, path_null, 0xbadc0ded, path_null, 0xdeadbeef, errstr); + + sys_io_uring_register(fd_null, 0, arg_iov, ARRAY_SIZE(iov)); + printf("io_uring_register(%u<%s>, IORING_REGISTER_BUFFERS" + ", [{iov_base=%p, iov_len=%lu}, {iov_base=%p, iov_len=%lu}]" + ", %u) = %s\n", + fd_null, path_null, iov[0].iov_base, + (unsigned long) iov[0].iov_len, + iov[1].iov_base, (unsigned long) iov[1].iov_len, + (unsigned int) ARRAY_SIZE(iov), errstr); + + sys_io_uring_register(fd_null, 2, arg_fds, ARRAY_SIZE(fds)); + printf("io_uring_register(%u<%s>, IORING_REGISTER_FILES" + ", [%u<%s>, %u<%s>], %u) = %s\n", + fd_null, path_null, fd_full, path_full, fd_null, path_null, + (unsigned int) ARRAY_SIZE(fds), errstr); + + puts("+++ exited with 0 +++"); + return 0; +} + +#else + +SKIP_MAIN_UNDEFINED("__NR_io_uring_register") + +#endif diff --git a/tests/io_uring_setup.c b/tests/io_uring_setup.c new file mode 100644 index 000000000..f48095bb3 --- /dev/null +++ b/tests/io_uring_setup.c @@ -0,0 +1,103 @@ +/* + * Check decoding of io_uring_setup syscall. + * + * Copyright (c) 2019 Dmitry V. Levin <ldv@altlinux.org> + * All rights reserved. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "tests.h" +#include <unistd.h> +#include <asm/unistd.h> +#include "scno.h" + +#if defined HAVE_LINUX_IO_URING_H && defined __NR_io_uring_setup + +# include <stdio.h> +# include <stdint.h> +# include <string.h> +# include <linux/io_uring.h> + +# include "print_fields.h" + +static const char *errstr; + +static long +sys_io_uring_setup(uint32_t nentries, const void *params) +{ + kernel_ulong_t fill = (kernel_ulong_t) 0xdefaced00000000ULL; + kernel_ulong_t bad = (kernel_ulong_t) 0xbadc0dedbadc0dedULL; + kernel_ulong_t arg1 = fill | nentries; + kernel_ulong_t arg2 = (unsigned long) params; + + long rc = syscall(__NR_io_uring_setup, arg1, arg2, bad, bad, bad, bad); + errstr = sprintrc(rc); + return rc; +} + +int +main(void) +{ + long rc; + TAIL_ALLOC_OBJECT_CONST_PTR(struct io_uring_params, params); + const void *efault = (const void *) params + 1; + + skip_if_unavailable("/proc/self/fd/"); + + sys_io_uring_setup(-1U, NULL); + printf("io_uring_setup(%u, NULL) = %s\n", -1U, errstr); + + sys_io_uring_setup(0, efault); + printf("io_uring_setup(%u, %p) = %s\n", 0, efault, errstr); + + fill_memory(params, sizeof(*params)); + params->flags = -1; + sys_io_uring_setup(1, params); + printf("io_uring_setup(%u, {flags=IORING_SETUP_IOPOLL" + "|IORING_SETUP_SQPOLL|IORING_SETUP_SQ_AFF|%#x" + ", sq_thread_cpu=%#x, sq_thread_idle=%u, resv={", + 1, -1U - 7, params->sq_thread_cpu, params->sq_thread_idle); + for (unsigned int i = 0; i < ARRAY_SIZE(params->resv); ++i) + printf("%s%#x", i ? ", " : "", params->resv[i]); + printf("}}) = %s\n", errstr); + + memset(params, 0, sizeof(*params)); + rc = sys_io_uring_setup(2, params); + printf("io_uring_setup(%u, {flags=0, sq_thread_cpu=0" + ", sq_thread_idle=0", 2); + if (rc < 0) + printf("}) = %s\n", errstr); + else + printf(", sq_entries=%u, cq_entries=%u" + ", sq_off={head=%u, tail=%u, ring_mask=%u" + ", ring_entries=%u, flags=%u, dropped=%u, array=%u}" + ", cq_off={head=%u, tail=%u, ring_mask=%u" + ", ring_entries=%u, overflow=%u, cqes=%u}" + "}) = %ld<anon_inode:[io_uring]>\n", + params->sq_entries, + params->cq_entries, + params->sq_off.head, + params->sq_off.tail, + params->sq_off.ring_mask, + params->sq_off.ring_entries, + params->sq_off.flags, + params->sq_off.dropped, + params->sq_off.array, + params->cq_off.head, + params->cq_off.tail, + params->cq_off.ring_mask, + params->cq_off.ring_entries, + params->cq_off.overflow, + params->cq_off.cqes, + rc); + + puts("+++ exited with 0 +++"); + return 0; +} + +#else + +SKIP_MAIN_UNDEFINED("HAVE_LINUX_IO_URING_H && __NR_io_uring_setup") + +#endif diff --git a/tests/pure_executables.list b/tests/pure_executables.list index 258b8c65f..372252095 100755 --- a/tests/pure_executables.list +++ b/tests/pure_executables.list @@ -120,6 +120,9 @@ inet-cmsg init_module inotify inotify_init1 +io_uring_enter +io_uring_register +io_uring_setup ioctl ioctl_block ioctl_dm diff --git a/xlat/uring_enter_flags.in b/xlat/uring_enter_flags.in new file mode 100644 index 000000000..609727802 --- /dev/null +++ b/xlat/uring_enter_flags.in @@ -0,0 +1,2 @@ +IORING_ENTER_GETEVENTS 1U +IORING_ENTER_SQ_WAKEUP 2U diff --git a/xlat/uring_register_opcodes.in b/xlat/uring_register_opcodes.in new file mode 100644 index 000000000..d98df2e72 --- /dev/null +++ b/xlat/uring_register_opcodes.in @@ -0,0 +1,4 @@ +IORING_REGISTER_BUFFERS 0U +IORING_UNREGISTER_BUFFERS 1U +IORING_REGISTER_FILES 2U +IORING_UNREGISTER_FILES 3U diff --git a/xlat/uring_setup_flags.in b/xlat/uring_setup_flags.in new file mode 100644 index 000000000..d44c7b1bd --- /dev/null +++ b/xlat/uring_setup_flags.in @@ -0,0 +1,3 @@ +IORING_SETUP_IOPOLL 1U +IORING_SETUP_SQPOLL 2U +IORING_SETUP_SQ_AFF 4U |