diff --git a/src/system/signal/info.rs b/src/system/signal/info.rs index 31c31dbd2..667762638 100644 --- a/src/system/signal/info.rs +++ b/src/system/signal/info.rs @@ -21,6 +21,11 @@ impl SignalInfo { /// Gets the PID that sent the signal. pub(crate) fn pid(&self) -> ProcessId { // FIXME: some signals don't set si_pid. + // + // SAFETY: this just fetches the `si_pid` field; since this is an integer, + // even if the information is nonsense it will not cause UB. Note that + // that a `ProcessId` does not have as type invariant that it always holds a valid + // process id, only that it is the appropriate type for storing such ids. unsafe { self.info.si_pid() } } diff --git a/src/system/signal/set.rs b/src/system/signal/set.rs index 5468a8172..0272aafb8 100644 --- a/src/system/signal/set.rs +++ b/src/system/signal/set.rs @@ -42,8 +42,11 @@ impl SignalAction { pub(super) fn register(&self, signal: SignalNumber) -> io::Result { let mut original_action = MaybeUninit::::zeroed(); + // SAFETY: `sigaction` expects a valid pointer, which we provide; the typecast is valid + // since SignalAction is a repr(transparent) newtype struct. cerr(unsafe { libc::sigaction(signal, &self.raw, original_action.as_mut_ptr().cast()) })?; + // SAFETY: `sigaction` will have properly initialized `original_action`. Ok(unsafe { original_action.assume_init() }) } } @@ -59,8 +62,10 @@ impl SignalSet { pub(crate) fn empty() -> io::Result { let mut set = MaybeUninit::::zeroed(); + // SAFETY: same as above cerr(unsafe { libc::sigemptyset(set.as_mut_ptr().cast()) })?; + // SAFETY: `sigemptyset` will have initialized `set` Ok(unsafe { set.assume_init() }) } @@ -68,16 +73,20 @@ impl SignalSet { pub(crate) fn full() -> io::Result { let mut set = MaybeUninit::::zeroed(); + // SAFETY: same as above cerr(unsafe { libc::sigfillset(set.as_mut_ptr().cast()) })?; + // SAFETY: `sigfillset` will have initialized `set` Ok(unsafe { set.assume_init() }) } fn sigprocmask(&self, how: libc::c_int) -> io::Result { let mut original_set = MaybeUninit::::zeroed(); + // SAFETY: same as above cerr(unsafe { libc::sigprocmask(how, &self.raw, original_set.as_mut_ptr().cast()) })?; + // SAFETY: `sigprocmask` will have initialized `set` Ok(unsafe { original_set.assume_init() }) } diff --git a/src/system/signal/stream.rs b/src/system/signal/stream.rs index f9ac67b68..aaac92e6c 100644 --- a/src/system/signal/stream.rs +++ b/src/system/signal/stream.rs @@ -62,6 +62,9 @@ impl SignalStream { pub(crate) fn recv(&self) -> io::Result { let mut info = MaybeUninit::::uninit(); let fd = self.rx.as_raw_fd(); + // SAFETY: type invariant for `SignalStream` ensures that `fd` is a valid file descriptor; + // furthermore, `info` is a valid pointer to `siginfo_t` (by virtue of `SignalInfo` being a + // transparent newtype for it), which has room for `SignalInfo::SIZE` bytes. let bytes = cerr(unsafe { libc::recv(fd, info.as_mut_ptr().cast(), SignalInfo::SIZE, 0) })?; if bytes as usize != SignalInfo::SIZE { @@ -92,6 +95,8 @@ pub(crate) fn register_handlers( })?; } + // SAFETY: if the above for-loop has terminated, every handler will have + // been written to via "MaybeUnit::new", and so is initialized. Ok(handlers.map(|(_, handler)| unsafe { handler.assume_init() })) }