1
- use libc:: { gid_t, uid_t} ;
1
+ use libc:: { gid_t, pid_t , uid_t} ;
2
2
3
3
/// Credentials of a process
4
4
#[ derive( Copy , Clone , Eq , PartialEq , Hash , Debug ) ]
5
5
pub struct UCred {
6
+ /// PID (process ID) of the process
7
+ pid : Option < pid_t > ,
6
8
/// UID (user ID) of the process
7
9
uid : uid_t ,
8
10
/// GID (group ID) of the process
@@ -19,19 +21,27 @@ impl UCred {
19
21
pub fn gid ( & self ) -> gid_t {
20
22
self . gid
21
23
}
24
+
25
+ /// Gets PID (process ID) of the process.
26
+ ///
27
+ /// This is only implemented under linux, android, IOS and MacOS
28
+ pub fn pid ( & self ) -> Option < pid_t > {
29
+ self . pid
30
+ }
22
31
}
23
32
24
33
#[ cfg( any( target_os = "linux" , target_os = "android" ) ) ]
25
34
pub ( crate ) use self :: impl_linux:: get_peer_cred;
26
35
27
36
#[ cfg( any(
28
37
target_os = "dragonfly" ,
29
- target_os = "macos" ,
30
- target_os = "ios" ,
31
38
target_os = "freebsd" ,
32
39
target_os = "netbsd" ,
33
40
target_os = "openbsd"
34
41
) ) ]
42
+ pub ( crate ) use self :: impl_bsd:: get_peer_cred;
43
+
44
+ #[ cfg( any( target_os = "macos" , target_os = "ios" ) ) ]
35
45
pub ( crate ) use self :: impl_macos:: get_peer_cred;
36
46
37
47
#[ cfg( any( target_os = "solaris" , target_os = "illumos" ) ) ]
@@ -77,6 +87,7 @@ pub(crate) mod impl_linux {
77
87
Ok ( super :: UCred {
78
88
uid : ucred. uid ,
79
89
gid : ucred. gid ,
90
+ pid : Some ( ucred. pid ) ,
80
91
} )
81
92
} else {
82
93
Err ( io:: Error :: last_os_error ( ) )
@@ -87,13 +98,11 @@ pub(crate) mod impl_linux {
87
98
88
99
#[ cfg( any(
89
100
target_os = "dragonfly" ,
90
- target_os = "macos" ,
91
- target_os = "ios" ,
92
101
target_os = "freebsd" ,
93
102
target_os = "netbsd" ,
94
103
target_os = "openbsd"
95
104
) ) ]
96
- pub ( crate ) mod impl_macos {
105
+ pub ( crate ) mod impl_bsd {
97
106
use crate :: net:: unix:: UnixStream ;
98
107
99
108
use libc:: getpeereid;
@@ -114,6 +123,54 @@ pub(crate) mod impl_macos {
114
123
Ok ( super :: UCred {
115
124
uid : uid. assume_init ( ) ,
116
125
gid : gid. assume_init ( ) ,
126
+ pid : None ,
127
+ } )
128
+ } else {
129
+ Err ( io:: Error :: last_os_error ( ) )
130
+ }
131
+ }
132
+ }
133
+ }
134
+
135
+ #[ cfg( any( target_os = "macos" , target_os = "ios" ) ) ]
136
+ pub ( crate ) mod impl_macos {
137
+ use crate :: net:: unix:: UnixStream ;
138
+
139
+ use libc:: { c_void, getpeereid, getsockopt, pid_t, LOCAL_PEEREPID , SOL_LOCAL } ;
140
+ use std:: io;
141
+ use std:: mem:: size_of;
142
+ use std:: mem:: MaybeUninit ;
143
+ use std:: os:: unix:: io:: AsRawFd ;
144
+
145
+ pub ( crate ) fn get_peer_cred ( sock : & UnixStream ) -> io:: Result < super :: UCred > {
146
+ unsafe {
147
+ let raw_fd = sock. as_raw_fd ( ) ;
148
+
149
+ let mut uid = MaybeUninit :: uninit ( ) ;
150
+ let mut gid = MaybeUninit :: uninit ( ) ;
151
+ let mut pid: MaybeUninit < pid_t > = MaybeUninit :: uninit ( ) ;
152
+ let mut pid_size: MaybeUninit < u32 > = MaybeUninit :: new ( size_of :: < pid_t > ( ) as u32 ) ;
153
+
154
+ if getsockopt (
155
+ raw_fd,
156
+ SOL_LOCAL ,
157
+ LOCAL_PEEREPID ,
158
+ pid. as_mut_ptr ( ) as * mut c_void ,
159
+ pid_size. as_mut_ptr ( ) ,
160
+ ) != 0
161
+ {
162
+ return Err ( io:: Error :: last_os_error ( ) ) ;
163
+ }
164
+
165
+ assert ! ( pid_size. assume_init( ) == ( size_of:: <pid_t>( ) as u32 ) ) ;
166
+
167
+ let ret = getpeereid ( raw_fd, uid. as_mut_ptr ( ) , gid. as_mut_ptr ( ) ) ;
168
+
169
+ if ret == 0 {
170
+ Ok ( super :: UCred {
171
+ uid : uid. assume_init ( ) ,
172
+ gid : gid. assume_init ( ) ,
173
+ pid : Some ( pid. assume_init ( ) ) ,
117
174
} )
118
175
} else {
119
176
Err ( io:: Error :: last_os_error ( ) )
@@ -154,7 +211,11 @@ pub(crate) mod impl_solaris {
154
211
155
212
ucred_free ( cred) ;
156
213
157
- Ok ( super :: UCred { uid, gid } )
214
+ Ok ( super :: UCred {
215
+ uid,
216
+ gid,
217
+ pid : None ,
218
+ } )
158
219
} else {
159
220
Err ( io:: Error :: last_os_error ( ) )
160
221
}
0 commit comments