From fea952f68f6eed53f75e66568d31efeca5bde19f Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Sun, 9 Nov 2025 07:59:43 -0800 Subject: [PATCH 1/2] Fix UB in an io_uring test, and add a safety comment. Add a safety comment to `io_uring_register` that the pointee must point to mutable memory. We should fix the API too, but that's a semver break, so I've filed #1545. Also, remove an entry from CHANGES.md that didn't happen. --- CHANGES.md | 6 ------ src/io_uring/mod.rs | 6 ++++++ tests/io_uring/register.rs | 14 ++++++++------ 3 files changed, 14 insertions(+), 12 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index fd5770da6..a13b83606 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -66,12 +66,6 @@ constant. [`IORING_REGISTER_FILES_SKIP`]: https://docs.rs/rustix/1/rustix/io_uring/constant.IORING_REGISTER_FILES_SKIP.html [`rustix::fs::CWD`]: https://docs.rs/rustix/1/rustix/fs/constant.CWD.html -[`rustix::io_uring::io_uring_register`] now has a [`IoringRegisterFlags`] -argument, and `rustix::io_uring::io_uring_register_with` is removed. - -[`rustix::io_uring::io_uring_register`]: https://docs.rs/rustix/1/rustix/io_uring/fn.io_uring_register.html -[`IoringRegisterFlags`]: https://docs.rs/rustix/1/rustix/io_uring/struct.IoringRegisterFlags.html - Several structs in [`rustix::io_uring`] are now marked `#[non_exhaustive]` because they contain padding or reserved fields. Instead of constructing them with field values and `..Default::default()`, construct them with diff --git a/src/io_uring/mod.rs b/src/io_uring/mod.rs index 5e3756812..f4084ef17 100644 --- a/src/io_uring/mod.rs +++ b/src/io_uring/mod.rs @@ -106,6 +106,9 @@ pub unsafe fn io_uring_setup(entries: u32, params: &mut io_uring_params) -> io:: /// responsible for ensuring that memory and resources are only accessed in /// valid ways. /// +/// If `opcode` is `IoringRegisterOp::RegisterRingFds`, `arg` must point to +/// mutable memory, despite being `*const`. +/// /// # References /// - [Linux] /// @@ -129,6 +132,9 @@ pub unsafe fn io_uring_register( /// responsible for ensuring that memory and resources are only accessed in /// valid ways. /// +/// If `opcode` is `IoringRegisterOp::RegisterRingFds`, `arg` must point to +/// mutable memory, despite being `*const`. +/// /// # References /// - [Linux] /// diff --git a/tests/io_uring/register.rs b/tests/io_uring/register.rs index 71e779570..02d6287aa 100644 --- a/tests/io_uring/register.rs +++ b/tests/io_uring/register.rs @@ -15,7 +15,7 @@ fn do_register( fd: FD, registered_fd: bool, opcode: IoringRegisterOp, - arg: *const c_void, + arg: *mut c_void, arg_nr: u32, ) -> Result<()> where @@ -27,8 +27,10 @@ where IoringRegisterFlags::default() }; + // Cast `arg` to `*const c_void` to match the current API. See + // . unsafe { - io_uring_register_with(fd, opcode, flags, arg, arg_nr)?; + io_uring_register_with(fd, opcode, flags, arg as *const c_void, arg_nr)?; } Ok(()) @@ -43,7 +45,7 @@ fn register_ring(fd: BorrowedFd<'_>) -> Result> { fd, false, IoringRegisterOp::RegisterRingFds, - (&update as *const io_uring_rsrc_update).cast::(), + (&mut update as *mut io_uring_rsrc_update).cast::(), 1, )?; @@ -63,7 +65,7 @@ where fd, true, IoringRegisterOp::UnregisterRingFds, - (&update as *const io_uring_rsrc_update).cast::(), + (&update as *const io_uring_rsrc_update as *mut io_uring_rsrc_update).cast::(), 1, )?; @@ -81,7 +83,7 @@ where fd, true, IoringRegisterOp::RegisterIowqMaxWorkers, - (&iowq_max_workers as *const [u32; 2]).cast::(), + (&iowq_max_workers as *const [u32; 2] as *mut [u32; 2]).cast::(), 2, )?; @@ -96,7 +98,7 @@ where fd, false, IoringRegisterOp::RegisterPbufRing, - (reg as *const io_uring_buf_reg).cast::(), + (reg as *const io_uring_buf_reg as *mut io_uring_buf_reg).cast::(), 1, ) } From 6dc03663d6414ab1f348a7e083bfc0505902d25c Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Sun, 9 Nov 2025 08:55:01 -0800 Subject: [PATCH 2/2] Remove `syscall_readonly` in `io_uring_register`. --- src/backend/linux_raw/io_uring/syscalls.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/backend/linux_raw/io_uring/syscalls.rs b/src/backend/linux_raw/io_uring/syscalls.rs index 3e61b7aa6..36edd4c0c 100644 --- a/src/backend/linux_raw/io_uring/syscalls.rs +++ b/src/backend/linux_raw/io_uring/syscalls.rs @@ -29,7 +29,9 @@ pub(crate) unsafe fn io_uring_register( arg: *const c_void, nr_args: u32, ) -> io::Result { - ret_c_uint(syscall_readonly!( + // This is not `syscall_readonly` because when `opcode` is + // `IoringRegisterOp::RegisterRingFds`, `arg`'s pointee is mutated. + ret_c_uint(syscall!( __NR_io_uring_register, fd, c_uint(opcode as u32), @@ -46,7 +48,9 @@ pub(crate) unsafe fn io_uring_register_with( arg: *const c_void, nr_args: u32, ) -> io::Result { - ret_c_uint(syscall_readonly!( + // This is not `syscall_readonly` because when `opcode` is + // `IoringRegisterOp::RegisterRingFds`, `arg`'s pointee is mutated. + ret_c_uint(syscall!( __NR_io_uring_register, fd, c_uint((opcode as u32) | bitflags_bits!(flags)),