Skip to content

Commit

Permalink
MacOS socket audit token (#2529)
Browse files Browse the repository at this point in the history
* Chore: Bump libc requirement

So the LOCAL_PEERTOKEN it adds may be guaranteed to be available.

Signed-off-by: Paul Mabileau <[email protected]>

* Refactor(sockopt): Use libc::SOL_LOCAL for LOCAL_PEER* options instead of 0

Should be more readable.

Signed-off-by: Paul Mabileau <[email protected]>

* Feat(sockopt): Add new wrapper around libc::LOCAL_PEERTOKEN

audit_token_t is taken from endpoint-sec-sys.

Signed-off-by: Paul Mabileau <[email protected]>

* Test(socket): Add small test for LocalPeerToken

Signed-off-by: Paul Mabileau <[email protected]>

* Docs: Add changelog entry

Signed-off-by: Paul Mabileau <[email protected]>

---------

Signed-off-by: Paul Mabileau <[email protected]>
  • Loading branch information
PaulDance authored Oct 30, 2024
1 parent 70f8fe0 commit a41a1f0
Show file tree
Hide file tree
Showing 5 changed files with 111 additions and 3 deletions.
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,
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

0 comments on commit a41a1f0

Please sign in to comment.