diff --git a/examples/kq.rs b/examples/kq.rs index fa0cbbd1e..04306224b 100644 --- a/examples/kq.rs +++ b/examples/kq.rs @@ -5,6 +5,7 @@ fn main() -> std::io::Result<()> { use rustix::event::kqueue::*; #[cfg(feature = "fs")] use rustix::{fd::AsRawFd, fs}; + use std::ptr::null_mut; let kq = kqueue()?; let mut out = Vec::with_capacity(10); @@ -25,7 +26,7 @@ fn main() -> std::io::Result<()> { times: 0, }, EventFlags::ADD, - 0, + null_mut(), ), #[cfg(feature = "fs")] Event::new( @@ -34,7 +35,7 @@ fn main() -> std::io::Result<()> { flags: VnodeEvents::WRITE | VnodeEvents::LINK | VnodeEvents::EXTEND, }, EventFlags::ADD | EventFlags::CLEAR, - 0, + null_mut(), ), Event::new( EventFilter::Timer { @@ -42,7 +43,7 @@ fn main() -> std::io::Result<()> { timer: Some(core::time::Duration::from_secs(1)), }, EventFlags::ADD, - 0, + null_mut(), ), Event::new( EventFilter::Timer { @@ -50,7 +51,7 @@ fn main() -> std::io::Result<()> { timer: Some(core::time::Duration::from_secs(2)), }, EventFlags::ADD | EventFlags::ONESHOT, - 0, + null_mut(), ), ]; diff --git a/src/event/kqueue.rs b/src/event/kqueue.rs index 56064999c..460432b05 100644 --- a/src/event/kqueue.rs +++ b/src/event/kqueue.rs @@ -24,7 +24,7 @@ pub struct Event { impl Event { /// Create a new `Event`. #[allow(clippy::needless_update)] - pub fn new(filter: EventFilter, flags: EventFlags, udata: isize) -> Event { + pub fn new(filter: EventFilter, flags: EventFlags, udata: *mut c::c_void) -> Event { let (ident, data, filter, fflags) = match filter { EventFilter::Read(fd) => (fd as uintptr_t, 0, c::EVFILT_READ, 0), EventFilter::Write(fd) => (fd as _, 0, c::EVFILT_WRITE, 0), @@ -78,7 +78,6 @@ impl Event { }, udata: { // On NetBSD, udata is an `isize` and not a pointer. - // TODO: Strict provenance, prevent int-to-ptr cast. udata as _ }, ..unsafe { zeroed() } @@ -92,10 +91,8 @@ impl Event { } /// Get the user data for this event. - pub fn udata(&self) -> isize { + pub fn udata(&self) -> *mut c::c_void { // On NetBSD, udata is an isize and not a pointer. - // TODO: Strict provenance, prevent ptr-to-int cast. - self.inner.udata as _ } diff --git a/src/ioctl/patterns.rs b/src/ioctl/patterns.rs index 0fb600556..ea0c714fc 100644 --- a/src/ioctl/patterns.rs +++ b/src/ioctl/patterns.rs @@ -200,14 +200,31 @@ unsafe impl<'a, Opcode: CompileTimeOpcode, T> Ioctl for Updater<'a, Opcode, T> { /// Implements an `ioctl` that passes an integer into the `ioctl`. pub struct IntegerSetter { /// The value to pass in. - value: usize, + /// + /// For strict provenance preservation, this is a pointer. + value: *mut c::c_void, /// The opcode. _opcode: PhantomData, } impl IntegerSetter { - /// Create a new integer `Ioctl` helper. + /// Create a new integer `Ioctl` helper containing a `usize`. + /// + /// # Safety + /// + /// - `Opcode` must provide a valid opcode. + /// - For this opcode, it must expect an integer. + /// - The integer is in the valid range for this opcode. + #[inline] + pub unsafe fn new_usize(value: usize) -> Self { + Self { + value: value as _, + _opcode: PhantomData, + } + } + + /// Create a new integer `Ioctl` helper containing a `*mut c_void`. /// /// # Safety /// @@ -215,7 +232,7 @@ impl IntegerSetter { /// - For this opcode, it must expect an integer. /// - The integer is in the valid range for this opcode. #[inline] - pub unsafe fn new(value: usize) -> Self { + pub unsafe fn new_pointer(value: &mut c::c_void) -> Self { Self { value, _opcode: PhantomData, @@ -230,8 +247,7 @@ unsafe impl Ioctl for IntegerSetter { const OPCODE: self::Opcode = Opcode::OPCODE; fn as_ptr(&mut self) -> *mut c::c_void { - // TODO: strict provenance - self.value as *mut c::c_void + self.value } unsafe fn output_from_ptr( diff --git a/tests/io/ioctl.rs b/tests/io/ioctl.rs index cc8cd987c..b5dac6fc7 100644 --- a/tests/io/ioctl.rs +++ b/tests/io/ioctl.rs @@ -26,7 +26,7 @@ fn test_int_setter() { // SAFETY: TUNSETOFFLOAD is defined for TUN. unsafe { - let code = IntegerSetter::>::new(0); + let code = IntegerSetter::>::new_usize(0); assert!(ioctl(&tun, code).is_err()); } }