diff --git a/tokio/src/net/unix/ucred.rs b/tokio/src/net/unix/ucred.rs index ef214a702fa..1760f50c994 100644 --- a/tokio/src/net/unix/ucred.rs +++ b/tokio/src/net/unix/ucred.rs @@ -1,8 +1,24 @@ use libc::{gid_t, uid_t}; +#[cfg(any( + target_os = "linux", + target_os = "android", + target_os = "macos", + target_os = "ios" +))] +use libc::pid_t; + /// Credentials of a process #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] pub struct UCred { + /// PID (process ID) of the process + #[cfg(any( + target_os = "linux", + target_os = "android", + target_os = "macos", + target_os = "ios" + ))] + pid: pid_t, /// UID (user ID) of the process uid: uid_t, /// GID (group ID) of the process @@ -19,6 +35,12 @@ impl UCred { pub fn gid(&self) -> gid_t { self.gid } + + /// Gets PID (process ID) of the process. + #[cfg(any(target_os = "linux", target_os = "android"))] + pub fn pid(&self) -> pid_t { + self.pid + } } #[cfg(any(target_os = "linux", target_os = "android"))] @@ -26,12 +48,13 @@ pub(crate) use self::impl_linux::get_peer_cred; #[cfg(any( target_os = "dragonfly", - target_os = "macos", - target_os = "ios", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd" ))] +pub(crate) use self::impl_bsd::get_peer_cred; + +#[cfg(any(target_os = "macos", target_os = "ios"))] pub(crate) use self::impl_macos::get_peer_cred; #[cfg(any(target_os = "solaris", target_os = "illumos"))] @@ -75,6 +98,7 @@ pub(crate) mod impl_linux { ); if ret == 0 && ucred_size as usize == mem::size_of::() { Ok(super::UCred { + pid: ucred.pid, uid: ucred.uid, gid: ucred.gid, }) @@ -87,13 +111,11 @@ pub(crate) mod impl_linux { #[cfg(any( target_os = "dragonfly", - target_os = "macos", - target_os = "ios", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd" ))] -pub(crate) mod impl_macos { +pub(crate) mod impl_bsd { use crate::net::unix::UnixStream; use libc::getpeereid; @@ -122,6 +144,50 @@ pub(crate) mod impl_macos { } } +#[cfg(any(target_os = "macos", target_os = "ios"))] +pub(crate) mod impl_macos { + use crate::net::unix::UnixStream; + + use libc::{c_void, getpeereid, getsockopt, pid_t, LOCAL_PEEREPID, SOL_LOCAL}; + use std::io; + use std::mem::size_of; + use std::mem::MaybeUninit; + use std::os::unix::io::AsRawFd; + + pub(crate) fn get_peer_cred(sock: &UnixStream) -> io::Result { + unsafe { + let raw_fd = sock.as_raw_fd(); + + let mut uid = MaybeUninit::uninit(); + let mut gid = MaybeUninit::uninit(); + let pid: pid_t = -1; + + if getsockopt( + raw_fd, + SOL_LOCAL, + LOCAL_PEEREPID, + pid as *mut c_void, + size_of::() as *mut u32, + ) != 0 + { + return Err(io::Error::last_os_error()); + } + + let ret = getpeereid(raw_fd, uid.as_mut_ptr(), gid.as_mut_ptr()); + + if ret == 0 { + Ok(super::UCred { + uid: uid.assume_init(), + gid: gid.assume_init(), + pid, + }) + } else { + Err(io::Error::last_os_error()) + } + } + } +} + #[cfg(any(target_os = "solaris", target_os = "illumos"))] pub(crate) mod impl_solaris { use crate::net::unix::UnixStream;