@@ -252,14 +252,12 @@ impl DomainSocketListenerBuilder {
252252impl GetMetadata for UnixStream {
253253 #[ cfg( feature = "unix-peer-credentials-authenticator" ) ]
254254 fn metadata ( & self ) -> Option < ConnectionMetadata > {
255- let ucred = self
256- . peer_cred ( )
255+ let ucred = peer_credentials:: peer_cred ( self )
257256 . map_err ( |err| {
258257 format_error ! (
259258 "Failed to grab peer credentials metadata from UnixStream" ,
260259 err
261- ) ;
262- err
260+ )
263261 } )
264262 . ok ( ) ?;
265263
@@ -275,3 +273,124 @@ impl GetMetadata for UnixStream {
275273 None
276274 }
277275}
276+
277+ // == IMPORTANT NOTE ==
278+ //
279+ // The code below has been cherry-picked from the following PR:
280+ //
281+ // https://github.com/rust-lang/rust/pull/75148
282+ //
283+ // At the time of writing (16/09/20), this patch is in the nightly Rust channel. To avoid needing
284+ // to use the nightly compiler to build Parsec, we have instead opted to cherry-pick the change
285+ // from the patch to allow us to use this feature 'early'.
286+ //
287+ // Once the feature hits stable, it should be safe to revert the commit that introduced the changes
288+ // below with `git revert`.
289+
290+ #[ cfg( feature = "unix-peer-credentials-authenticator" ) ]
291+ mod peer_credentials {
292+ use libc:: { gid_t, pid_t, uid_t} ;
293+
294+ /// Credentials for a UNIX process for credentials passing.
295+ #[ derive( Clone , Copy , Debug , Eq , Hash , PartialEq ) ]
296+ pub struct UCred {
297+ /// The UID part of the peer credential. This is the effective UID of the process at the domain
298+ /// socket's endpoint.
299+ pub uid : uid_t ,
300+ /// The GID part of the peer credential. This is the effective GID of the process at the domain
301+ /// socket's endpoint.
302+ pub gid : gid_t ,
303+ /// The PID part of the peer credential. This field is optional because the PID part of the
304+ /// peer credentials is not supported on every platform. On platforms where the mechanism to
305+ /// discover the PID exists, this field will be populated to the PID of the process at the
306+ /// domain socket's endpoint. Otherwise, it will be set to None.
307+ pub pid : Option < pid_t > ,
308+ }
309+
310+ #[ cfg( any( target_os = "android" , target_os = "linux" ) ) ]
311+ pub use self :: impl_linux:: peer_cred;
312+
313+ #[ cfg( any(
314+ target_os = "dragonfly" ,
315+ target_os = "freebsd" ,
316+ target_os = "ios" ,
317+ target_os = "macos" ,
318+ target_os = "openbsd"
319+ ) ) ]
320+ pub use self :: impl_bsd:: peer_cred;
321+
322+ #[ cfg( any( target_os = "linux" , target_os = "android" ) ) ]
323+ pub mod impl_linux {
324+ use super :: UCred ;
325+ use libc:: { c_void, getsockopt, socklen_t, ucred, SOL_SOCKET , SO_PEERCRED } ;
326+ use std:: os:: unix:: io:: AsRawFd ;
327+ use std:: os:: unix:: net:: UnixStream ;
328+ use std:: { io, mem} ;
329+
330+ pub fn peer_cred ( socket : & UnixStream ) -> io:: Result < UCred > {
331+ let ucred_size = mem:: size_of :: < ucred > ( ) ;
332+
333+ // Trivial sanity checks.
334+ assert ! ( mem:: size_of:: <u32 >( ) <= mem:: size_of:: <usize >( ) ) ;
335+ assert ! ( ucred_size <= u32 :: MAX as usize ) ;
336+
337+ let mut ucred_size = ucred_size as socklen_t ;
338+ let mut ucred: ucred = ucred {
339+ pid : 1 ,
340+ uid : 1 ,
341+ gid : 1 ,
342+ } ;
343+
344+ unsafe {
345+ let ret = getsockopt (
346+ socket. as_raw_fd ( ) ,
347+ SOL_SOCKET ,
348+ SO_PEERCRED ,
349+ & mut ucred as * mut ucred as * mut c_void ,
350+ & mut ucred_size,
351+ ) ;
352+
353+ if ret == 0 && ucred_size as usize == mem:: size_of :: < ucred > ( ) {
354+ Ok ( UCred {
355+ uid : ucred. uid ,
356+ gid : ucred. gid ,
357+ pid : Some ( ucred. pid ) ,
358+ } )
359+ } else {
360+ Err ( io:: Error :: last_os_error ( ) )
361+ }
362+ }
363+ }
364+ }
365+
366+ #[ cfg( any(
367+ target_os = "dragonfly" ,
368+ target_os = "macos" ,
369+ target_os = "ios" ,
370+ target_os = "freebsd" ,
371+ target_os = "openbsd"
372+ ) ) ]
373+ pub mod impl_bsd {
374+ use super :: UCred ;
375+ use std:: io;
376+ use std:: os:: unix:: io:: AsRawFd ;
377+ use std:: os:: unix:: net:: UnixStream ;
378+
379+ pub fn peer_cred ( socket : & UnixStream ) -> io:: Result < UCred > {
380+ let mut cred = UCred {
381+ uid : 1 ,
382+ gid : 1 ,
383+ pid : None ,
384+ } ;
385+ unsafe {
386+ let ret = libc:: getpeereid ( socket. as_raw_fd ( ) , & mut cred. uid , & mut cred. gid ) ;
387+
388+ if ret == 0 {
389+ Ok ( cred)
390+ } else {
391+ Err ( io:: Error :: last_os_error ( ) )
392+ }
393+ }
394+ }
395+ }
396+ }
0 commit comments