Skip to content

Commit 3e853c8

Browse files
authored
Fix UB in an io_uring test, and add a safety comment. (#1547)
* 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. * Remove `syscall_readonly` in `io_uring_register`.
1 parent 8626154 commit 3e853c8

File tree

4 files changed

+20
-14
lines changed

4 files changed

+20
-14
lines changed

CHANGES.md

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -66,12 +66,6 @@ constant.
6666
[`IORING_REGISTER_FILES_SKIP`]: https://docs.rs/rustix/1/rustix/io_uring/constant.IORING_REGISTER_FILES_SKIP.html
6767
[`rustix::fs::CWD`]: https://docs.rs/rustix/1/rustix/fs/constant.CWD.html
6868

69-
[`rustix::io_uring::io_uring_register`] now has a [`IoringRegisterFlags`]
70-
argument, and `rustix::io_uring::io_uring_register_with` is removed.
71-
72-
[`rustix::io_uring::io_uring_register`]: https://docs.rs/rustix/1/rustix/io_uring/fn.io_uring_register.html
73-
[`IoringRegisterFlags`]: https://docs.rs/rustix/1/rustix/io_uring/struct.IoringRegisterFlags.html
74-
7569
Several structs in [`rustix::io_uring`] are now marked `#[non_exhaustive]`
7670
because they contain padding or reserved fields. Instead of constructing
7771
them with field values and `..Default::default()`, construct them with

src/backend/linux_raw/io_uring/syscalls.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,9 @@ pub(crate) unsafe fn io_uring_register(
2929
arg: *const c_void,
3030
nr_args: u32,
3131
) -> io::Result<u32> {
32-
ret_c_uint(syscall_readonly!(
32+
// This is not `syscall_readonly` because when `opcode` is
33+
// `IoringRegisterOp::RegisterRingFds`, `arg`'s pointee is mutated.
34+
ret_c_uint(syscall!(
3335
__NR_io_uring_register,
3436
fd,
3537
c_uint(opcode as u32),
@@ -46,7 +48,9 @@ pub(crate) unsafe fn io_uring_register_with(
4648
arg: *const c_void,
4749
nr_args: u32,
4850
) -> io::Result<u32> {
49-
ret_c_uint(syscall_readonly!(
51+
// This is not `syscall_readonly` because when `opcode` is
52+
// `IoringRegisterOp::RegisterRingFds`, `arg`'s pointee is mutated.
53+
ret_c_uint(syscall!(
5054
__NR_io_uring_register,
5155
fd,
5256
c_uint((opcode as u32) | bitflags_bits!(flags)),

src/io_uring/mod.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,9 @@ pub unsafe fn io_uring_setup(entries: u32, params: &mut io_uring_params) -> io::
106106
/// responsible for ensuring that memory and resources are only accessed in
107107
/// valid ways.
108108
///
109+
/// If `opcode` is `IoringRegisterOp::RegisterRingFds`, `arg` must point to
110+
/// mutable memory, despite being `*const`.
111+
///
109112
/// # References
110113
/// - [Linux]
111114
///
@@ -129,6 +132,9 @@ pub unsafe fn io_uring_register<Fd: AsFd>(
129132
/// responsible for ensuring that memory and resources are only accessed in
130133
/// valid ways.
131134
///
135+
/// If `opcode` is `IoringRegisterOp::RegisterRingFds`, `arg` must point to
136+
/// mutable memory, despite being `*const`.
137+
///
132138
/// # References
133139
/// - [Linux]
134140
///

tests/io_uring/register.rs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ fn do_register<FD>(
1515
fd: FD,
1616
registered_fd: bool,
1717
opcode: IoringRegisterOp,
18-
arg: *const c_void,
18+
arg: *mut c_void,
1919
arg_nr: u32,
2020
) -> Result<()>
2121
where
@@ -27,8 +27,10 @@ where
2727
IoringRegisterFlags::default()
2828
};
2929

30+
// Cast `arg` to `*const c_void` to match the current API. See
31+
// <https://github.com/bytecodealliance/rustix/issues/1545>.
3032
unsafe {
31-
io_uring_register_with(fd, opcode, flags, arg, arg_nr)?;
33+
io_uring_register_with(fd, opcode, flags, arg as *const c_void, arg_nr)?;
3234
}
3335

3436
Ok(())
@@ -43,7 +45,7 @@ fn register_ring(fd: BorrowedFd<'_>) -> Result<BorrowedFd<'_>> {
4345
fd,
4446
false,
4547
IoringRegisterOp::RegisterRingFds,
46-
(&update as *const io_uring_rsrc_update).cast::<c_void>(),
48+
(&mut update as *mut io_uring_rsrc_update).cast::<c_void>(),
4749
1,
4850
)?;
4951

@@ -63,7 +65,7 @@ where
6365
fd,
6466
true,
6567
IoringRegisterOp::UnregisterRingFds,
66-
(&update as *const io_uring_rsrc_update).cast::<c_void>(),
68+
(&update as *const io_uring_rsrc_update as *mut io_uring_rsrc_update).cast::<c_void>(),
6769
1,
6870
)?;
6971

@@ -81,7 +83,7 @@ where
8183
fd,
8284
true,
8385
IoringRegisterOp::RegisterIowqMaxWorkers,
84-
(&iowq_max_workers as *const [u32; 2]).cast::<c_void>(),
86+
(&iowq_max_workers as *const [u32; 2] as *mut [u32; 2]).cast::<c_void>(),
8587
2,
8688
)?;
8789

@@ -96,7 +98,7 @@ where
9698
fd,
9799
false,
98100
IoringRegisterOp::RegisterPbufRing,
99-
(reg as *const io_uring_buf_reg).cast::<c_void>(),
101+
(reg as *const io_uring_buf_reg as *mut io_uring_buf_reg).cast::<c_void>(),
100102
1,
101103
)
102104
}

0 commit comments

Comments
 (0)