diff --git a/library/std/src/os/linux/process.rs b/library/std/src/os/linux/process.rs index 6daff0f003c..e3e7143c851 100644 --- a/library/std/src/os/linux/process.rs +++ b/library/std/src/os/linux/process.rs @@ -3,7 +3,7 @@ #![unstable(feature = "linux_pidfd", issue = "82971")] use crate::io::Result; -use crate::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd}; +use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd}; use crate::process; use crate::sealed::Sealed; #[cfg(not(doc))] @@ -69,19 +69,37 @@ impl IntoInner for PidFd { impl AsRawFd for PidFd { fn as_raw_fd(&self) -> RawFd { - self.as_inner().raw() + self.as_inner().as_raw_fd() } } impl FromRawFd for PidFd { unsafe fn from_raw_fd(fd: RawFd) -> Self { - Self::from_inner(FileDesc::new(fd)) + Self::from_inner(FileDesc::from_raw_fd(fd)) } } impl IntoRawFd for PidFd { fn into_raw_fd(self) -> RawFd { - self.into_inner().into_raw() + self.into_inner().into_raw_fd() + } +} + +impl AsFd for PidFd { + fn as_fd(&self) -> BorrowedFd<'_> { + self.as_inner().as_fd() + } +} + +impl From for PidFd { + fn from(fd: OwnedFd) -> Self { + Self::from_inner(FileDesc::from_inner(fd)) + } +} + +impl From for OwnedFd { + fn from(pid_fd: PidFd) -> Self { + pid_fd.into_inner().into_inner() } } diff --git a/library/std/src/sys/unix/process/process_unix.rs b/library/std/src/sys/unix/process/process_unix.rs index 4b210d6af13..818f9308c19 100644 --- a/library/std/src/sys/unix/process/process_unix.rs +++ b/library/std/src/sys/unix/process/process_unix.rs @@ -4,6 +4,7 @@ use crate::io::{self, Error, ErrorKind}; use crate::mem; use crate::num::NonZeroI32; use crate::os::raw::NonZero_c_int; +use crate::os::unix::io::FromRawFd; use crate::ptr; use crate::sys; use crate::sys::cvt; @@ -97,7 +98,9 @@ impl Command { drop(env_lock); drop(output); - let mut p = Process::new(pid, pidfd); + // Safety: We obtained the pidfd from calling `clone3` with + // `CLONE_PIDFD` so it's valid an otherwise unowned. + let mut p = unsafe { Process::new(pid, pidfd) }; let mut bytes = [0; 8]; // loop to handle EINTR @@ -446,7 +449,8 @@ impl Command { None => None, }; - let mut p = Process::new(0, -1); + // Safety: -1 indicates we don't have a pidfd. + let mut p = unsafe { Process::new(0, -1) }; struct PosixSpawnFileActions<'a>(&'a mut MaybeUninit); @@ -545,14 +549,16 @@ pub struct Process { impl Process { #[cfg(target_os = "linux")] - fn new(pid: pid_t, pidfd: pid_t) -> Self { + unsafe fn new(pid: pid_t, pidfd: pid_t) -> Self { use crate::sys_common::FromInner; - let pidfd = (pidfd >= 0).then(|| PidFd::from_inner(sys::fd::FileDesc::new(pidfd))); + // Safety: If `pidfd` is nonnegative, we assume it's valid and otherwise unowned. + let pidfd = (pidfd >= 0) + .then(|| PidFd::from_inner(unsafe { sys::fd::FileDesc::from_raw_fd(pidfd) })); Process { pid, status: None, pidfd } } #[cfg(not(target_os = "linux"))] - fn new(pid: pid_t, _pidfd: pid_t) -> Self { + unsafe fn new(pid: pid_t, _pidfd: pid_t) -> Self { Process { pid, status: None } }