mirror of
https://github.com/tokio-rs/tokio.git
synced 2026-08-19 00:00:09 +02:00
net: implement UCred::pid on FreeBSD (#8086)
This commit is contained in:
+8
-1
@@ -1,4 +1,4 @@
|
||||
316
|
||||
323
|
||||
&
|
||||
+
|
||||
<
|
||||
@@ -189,14 +189,17 @@ mutex
|
||||
Mutex
|
||||
Nagle
|
||||
namespace
|
||||
NetBSD
|
||||
nonblocking
|
||||
nondecreasing
|
||||
noop
|
||||
ntasks
|
||||
NTO
|
||||
NUMA
|
||||
ok
|
||||
oneshot
|
||||
opcode
|
||||
OpenBSD
|
||||
ORed
|
||||
os
|
||||
parker
|
||||
@@ -213,6 +216,7 @@ RAII
|
||||
RCU
|
||||
reallocations
|
||||
recv's
|
||||
Redox
|
||||
refactors
|
||||
refcount
|
||||
refcounting
|
||||
@@ -279,6 +283,7 @@ tokio's
|
||||
Tokio's
|
||||
tuple
|
||||
Tuple
|
||||
tvOS
|
||||
tx
|
||||
udp
|
||||
UDP
|
||||
@@ -306,6 +311,7 @@ vec
|
||||
versa
|
||||
versioned
|
||||
versioning
|
||||
visionOS
|
||||
vtable
|
||||
waker
|
||||
wakers
|
||||
@@ -313,5 +319,6 @@ Wakers
|
||||
wakeup
|
||||
wakeups
|
||||
WASI
|
||||
watchOS
|
||||
workstealing
|
||||
ZST
|
||||
|
||||
@@ -24,8 +24,10 @@ impl UCred {
|
||||
|
||||
/// Gets PID (process ID) of the process.
|
||||
///
|
||||
/// This is only implemented under Linux, Android, iOS, macOS, Solaris,
|
||||
/// Illumos and Cygwin. On other platforms this will always return `None`.
|
||||
/// This is implemented under Linux, Android, OpenBSD, FreeBSD (since
|
||||
/// FreeBSD 13), NetBSD, NTO, iOS, macOS, tvOS, watchOS, visionOS,
|
||||
/// Solaris, Illumos, Cygwin, Haiku, and Redox. On other platforms this
|
||||
/// will always return `None`.
|
||||
pub fn pid(&self) -> Option<unix::pid_t> {
|
||||
self.pid
|
||||
}
|
||||
@@ -44,8 +46,11 @@ pub(crate) use self::impl_linux::get_peer_cred;
|
||||
#[cfg(any(target_os = "netbsd", target_os = "nto"))]
|
||||
pub(crate) use self::impl_netbsd::get_peer_cred;
|
||||
|
||||
#[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
|
||||
pub(crate) use self::impl_bsd::get_peer_cred;
|
||||
#[cfg(target_os = "dragonfly")]
|
||||
pub(crate) use self::impl_dragonfly::get_peer_cred;
|
||||
|
||||
#[cfg(target_os = "freebsd")]
|
||||
pub(crate) use self::impl_freebsd::get_peer_cred;
|
||||
|
||||
#[cfg(any(
|
||||
target_os = "macos",
|
||||
@@ -172,8 +177,8 @@ pub(crate) mod impl_netbsd {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
|
||||
pub(crate) mod impl_bsd {
|
||||
#[cfg(target_os = "dragonfly")]
|
||||
pub(crate) mod impl_dragonfly {
|
||||
use crate::net::unix::{self, UnixStream};
|
||||
|
||||
use libc::getpeereid;
|
||||
@@ -203,6 +208,74 @@ pub(crate) mod impl_bsd {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "freebsd")]
|
||||
pub(crate) mod impl_freebsd {
|
||||
use crate::net::unix::{self, UnixStream};
|
||||
|
||||
use libc::{c_void, getsockopt, socklen_t, xucred, LOCAL_PEERCRED, XUCRED_VERSION};
|
||||
use std::io;
|
||||
use std::mem::{size_of, MaybeUninit};
|
||||
use std::os::unix::io::AsRawFd;
|
||||
|
||||
pub(crate) fn get_peer_cred(sock: &UnixStream) -> io::Result<super::UCred> {
|
||||
// `SOL_LOCAL` is not re-exported by `libc` for FreeBSD; it is defined
|
||||
// as 0 in `<sys/un.h>`.
|
||||
const SOL_LOCAL: libc::c_int = 0;
|
||||
|
||||
unsafe {
|
||||
let raw_fd = sock.as_raw_fd();
|
||||
|
||||
let mut xucred = MaybeUninit::<xucred>::zeroed();
|
||||
let mut len = size_of::<xucred>() as socklen_t;
|
||||
|
||||
let ret = getsockopt(
|
||||
raw_fd,
|
||||
SOL_LOCAL,
|
||||
LOCAL_PEERCRED,
|
||||
xucred.as_mut_ptr() as *mut c_void,
|
||||
&mut len,
|
||||
);
|
||||
|
||||
if ret != 0 {
|
||||
return Err(io::Error::last_os_error());
|
||||
}
|
||||
if len as usize != size_of::<xucred>() {
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::InvalidData,
|
||||
"unexpected xucred size from LOCAL_PEERCRED",
|
||||
));
|
||||
}
|
||||
|
||||
let xucred = xucred.assume_init();
|
||||
|
||||
// Match `getpeereid(3)` and reject any `xucred` whose version we
|
||||
// don't know how to interpret.
|
||||
if xucred.cr_version != XUCRED_VERSION {
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::InvalidData,
|
||||
"unexpected xucred version from LOCAL_PEERCRED",
|
||||
));
|
||||
}
|
||||
|
||||
// `cr_pid` is populated by the kernel since FreeBSD 13. PID 0 is
|
||||
// the kernel scheduler and never a real userland peer, so we
|
||||
// surface it as `None` rather than a misleading `Some(0)`.
|
||||
let pid = match xucred.cr_pid__c_anonymous_union.cr_pid {
|
||||
0 => None,
|
||||
p => Some(p as unix::pid_t),
|
||||
};
|
||||
|
||||
// `xucred` carries the effective uid in `cr_uid` and the effective
|
||||
// gid in `cr_groups[0]`, matching what `getpeereid(2)` returns.
|
||||
Ok(super::UCred {
|
||||
uid: xucred.cr_uid as unix::uid_t,
|
||||
gid: xucred.cr_groups[0] as unix::gid_t,
|
||||
pid,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(
|
||||
target_os = "macos",
|
||||
target_os = "ios",
|
||||
|
||||
@@ -23,4 +23,35 @@ async fn test_socket_pair() {
|
||||
|
||||
assert_eq!(cred_a.uid(), uid);
|
||||
assert_eq!(cred_a.gid(), gid);
|
||||
|
||||
// On platforms where `UCred::pid` is implemented and the kernel
|
||||
// populates it, both ends of a `socketpair` must report the current
|
||||
// process's PID.
|
||||
//
|
||||
// FreeBSD COMPAT32 (32-bit binary on a 64-bit kernel) leaves `cr_pid`
|
||||
// zeroed pending FreeBSD bug 294833; the assertion is gated on 64-bit
|
||||
// FreeBSD until that fix ships.
|
||||
#[cfg(any(
|
||||
target_os = "linux",
|
||||
target_os = "android",
|
||||
target_os = "openbsd",
|
||||
all(target_os = "freebsd", target_pointer_width = "64"),
|
||||
target_os = "netbsd",
|
||||
target_os = "nto",
|
||||
target_os = "macos",
|
||||
target_os = "ios",
|
||||
target_os = "tvos",
|
||||
target_os = "watchos",
|
||||
target_os = "visionos",
|
||||
target_os = "solaris",
|
||||
target_os = "illumos",
|
||||
target_os = "redox",
|
||||
target_os = "haiku",
|
||||
target_os = "cygwin",
|
||||
))]
|
||||
{
|
||||
let pid = unsafe { libc::getpid() };
|
||||
assert_eq!(cred_a.pid(), Some(pid));
|
||||
assert_eq!(cred_b.pid(), Some(pid));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user