Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MacOS socket audit token #2529

Merged
merged 5 commits into from
Oct 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ targets = [
]

[dependencies]
libc = { version = "0.2.158", features = ["extra_traits"] }
libc = { version = "0.2.160", features = ["extra_traits"] }
bitflags = "2.3.3"
cfg-if = "1.0"
pin-utils = { version = "0.1.0", optional = true }
Expand Down
1 change: 1 addition & 0 deletions changelog/2529.added.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add support for `libc::LOCAL_PEERTOKEN` in `getsockopt`.
57 changes: 57 additions & 0 deletions src/sys/socket/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -499,6 +499,63 @@ cfg_if! {
}
}

cfg_if! {
if #[cfg(apple_targets)] {
use std::fmt;

/// Return type of [`LocalPeerToken`].
///
/// The audit token is an opaque token which identifies Mach tasks and
/// senders of Mach messages as subjects to the BSM audit system. Only
/// the appropriate BSM library routines should be used to interpret
/// the contents of the audit token as the representation of the
/// subject identity within the token may change over time.
///
/// Starting with macOS 11, almost all audit functions have been
/// deprecated (see the system header `bsm/libbsm.h`), do not use them
/// if your program target more recent versions of macOS.
///
/// [`LocalPeerToken`]: crate::sys::socket::sockopt::LocalPeerToken
#[repr(C)]
#[derive(Default, Copy, Clone, PartialEq, Eq, Hash)]
pub struct audit_token_t {
/// Value of the token.
///
/// This is considered an opaque value, do not rely on its format.
pub val: [libc::c_uint; 8],
}

// Make the debug representation a hex string to make it shorter and clearer.
impl fmt::Debug for audit_token_t {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_tuple("audit_token_t")
.field(&format!("0x{:08X}", self))
.finish()
}
}

impl fmt::LowerHex for audit_token_t {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
for v in self.val {
fmt::LowerHex::fmt(&v, f)?;
}

Ok(())
}
}

impl fmt::UpperHex for audit_token_t {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
for v in self.val {
fmt::UpperHex::fmt(&v, f)?;
}

Ok(())
}
}
}
}

feature! {
#![feature = "net"]
/// Request for multicast socket operations
Expand Down
24 changes: 22 additions & 2 deletions src/sys/socket/sockopt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -563,7 +563,7 @@ sockopt_impl!(
libc::SO_KEEPALIVE,
bool
);
#[cfg(any(freebsdlike, apple_targets))]
#[cfg(freebsdlike)]
sockopt_impl!(
/// Get the credentials of the peer process of a connected unix domain
/// socket.
Expand All @@ -574,14 +574,34 @@ sockopt_impl!(
super::XuCred
);
#[cfg(apple_targets)]
sockopt_impl!(
/// Get the credentials of the peer process of a connected unix domain
/// socket.
LocalPeerCred,
GetOnly,
libc::SOL_LOCAL,
PaulDance marked this conversation as resolved.
Show resolved Hide resolved
libc::LOCAL_PEERCRED,
super::XuCred
);
#[cfg(apple_targets)]
sockopt_impl!(
/// Get the PID of the peer process of a connected unix domain socket.
LocalPeerPid,
GetOnly,
0,
libc::SOL_LOCAL,
libc::LOCAL_PEERPID,
libc::c_int
);
#[cfg(apple_targets)]
sockopt_impl!(
/// Get the audit token of the peer process of a connected unix domain
/// socket.
LocalPeerToken,
GetOnly,
libc::SOL_LOCAL,
libc::LOCAL_PEERTOKEN,
super::audit_token_t
);
#[cfg(linux_android)]
sockopt_impl!(
/// Return the credentials of the foreign process connected to this socket.
Expand Down
30 changes: 30 additions & 0 deletions test/sys/test_sockopt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,36 @@ pub fn test_local_peer_pid() {
assert_eq!(pid, std::process::id() as _);
}

#[cfg(apple_targets)]
#[test]
pub fn test_local_peer_token() {
use nix::sys::socket::{audit_token_t, socketpair};

#[link(name = "bsm", kind = "dylib")]
extern "C" {
/// Extract the process ID from an `audit_token_t`, used to identify
/// Mach tasks and senders of Mach messages as subjects of the audit
/// system.
///
/// - `atoken`: The Mach audit token.
/// - Returns: The process ID extracted from the Mach audit token.
fn audit_token_to_pid(atoken: audit_token_t) -> libc::pid_t;
}

let (fd1, _fd2) = socketpair(
AddressFamily::Unix,
SockType::Stream,
None,
SockFlag::empty(),
)
.unwrap();
let audit_token = getsockopt(&fd1, sockopt::LocalPeerToken).unwrap();
assert_eq!(
unsafe { audit_token_to_pid(audit_token) },
std::process::id() as _
);
}

#[cfg(target_os = "linux")]
#[test]
fn is_so_mark_functional() {
Expand Down