diff --git a/src/sys/socket/mod.rs b/src/sys/socket/mod.rs index e34b91943a..1da32c3dbd 100644 --- a/src/sys/socket/mod.rs +++ b/src/sys/socket/mod.rs @@ -196,6 +196,15 @@ cfg_if! { pub struct UnixCredentials(libc::ucred); impl UnixCredentials { + /// Creates a new instance with the credentials of the current process + pub fn new() -> Self { + UnixCredentials(libc::ucred { + pid: crate::unistd::getpid().as_raw(), + uid: crate::unistd::getuid().as_raw(), + gid: crate::unistd::getgid().as_raw(), + }) + } + /// Returns the process identifier pub fn pid(&self) -> libc::pid_t { self.0.pid @@ -232,6 +241,19 @@ cfg_if! { pub struct UnixCredentials(libc::cmsgcred); impl UnixCredentials { + /// Creates a new instance with the credentials of the current process + pub fn new() -> Self { + // The kernel overwrites it when sending SCM_CREDS + UnixCredentials(libc::cmsgcred { + cmcred_pid: 0, + cmcred_uid: 0, + cmcred_euid: 0, + cmcred_gid: 0, + cmcred_ngroups: 0, + cmcred_groups: [0; libc::CMGROUP_MAX], + }) + } + /// Returns the process identifier pub fn pid(&self) -> libc::pid_t { self.0.cmcred_pid diff --git a/test/sys/test_socket.rs b/test/sys/test_socket.rs index bd5c373bc7..4971bf81e8 100644 --- a/test/sys/test_socket.rs +++ b/test/sys/test_socket.rs @@ -540,28 +540,31 @@ pub fn test_sendmsg_empty_cmsgs() { } } -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(any( + target_os = "android", + target_os = "linux", + target_os = "freebsd", + target_os = "dragonfly", +))] #[test] fn test_scm_credentials() { - use libc; use nix::sys::uio::IoVec; use nix::unistd::{close, getpid, getuid, getgid}; use nix::sys::socket::{socketpair, sendmsg, recvmsg, setsockopt, AddressFamily, SockType, SockFlag, - ControlMessage, ControlMessageOwned, MsgFlags}; + ControlMessage, ControlMessageOwned, MsgFlags, + UnixCredentials}; + #[cfg(any(target_os = "android", target_os = "linux"))] use nix::sys::socket::sockopt::PassCred; let (send, recv) = socketpair(AddressFamily::Unix, SockType::Stream, None, SockFlag::empty()) .unwrap(); + #[cfg(any(target_os = "android", target_os = "linux"))] setsockopt(recv, PassCred, &true).unwrap(); { let iov = [IoVec::from_slice(b"hello")]; - let cred = libc::ucred { - pid: getpid().as_raw(), - uid: getuid().as_raw(), - gid: getgid().as_raw(), - }.into(); + let cred = UnixCredentials::new(); let cmsg = ControlMessage::ScmCredentials(&cred); assert_eq!(sendmsg(send, &iov, &[cmsg], MsgFlags::empty(), None).unwrap(), 5); close(send).unwrap(); @@ -570,7 +573,7 @@ fn test_scm_credentials() { { let mut buf = [0u8; 5]; let iov = [IoVec::from_mut_slice(&mut buf[..])]; - let mut cmsgspace = cmsg_space!(libc::ucred); + let mut cmsgspace = cmsg_space!(UnixCredentials); let msg = recvmsg(recv, &iov, Some(&mut cmsgspace), MsgFlags::empty()).unwrap(); let mut received_cred = None; @@ -582,7 +585,7 @@ fn test_scm_credentials() { assert_eq!(cred.gid(), getgid().as_raw()); received_cred = Some(cred); } else { - panic!("unexpected cmsg"); + panic!("unexpected cmsg {:?}", cmsg); } } received_cred.expect("no creds received");