Skip to content

Commit a41a1f0

Browse files
authored
MacOS socket audit token (#2529)
* Chore: Bump libc requirement So the LOCAL_PEERTOKEN it adds may be guaranteed to be available. Signed-off-by: Paul Mabileau <paul.mabileau@harfanglab.fr> * Refactor(sockopt): Use libc::SOL_LOCAL for LOCAL_PEER* options instead of 0 Should be more readable. Signed-off-by: Paul Mabileau <paul.mabileau@harfanglab.fr> * Feat(sockopt): Add new wrapper around libc::LOCAL_PEERTOKEN audit_token_t is taken from endpoint-sec-sys. Signed-off-by: Paul Mabileau <paul.mabileau@harfanglab.fr> * Test(socket): Add small test for LocalPeerToken Signed-off-by: Paul Mabileau <paul.mabileau@harfanglab.fr> * Docs: Add changelog entry Signed-off-by: Paul Mabileau <paul.mabileau@harfanglab.fr> --------- Signed-off-by: Paul Mabileau <paul.mabileau@harfanglab.fr>
1 parent 70f8fe0 commit a41a1f0

File tree

5 files changed

+111
-3
lines changed

5 files changed

+111
-3
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ targets = [
2828
]
2929

3030
[dependencies]
31-
libc = { version = "0.2.158", features = ["extra_traits"] }
31+
libc = { version = "0.2.160", features = ["extra_traits"] }
3232
bitflags = "2.3.3"
3333
cfg-if = "1.0"
3434
pin-utils = { version = "0.1.0", optional = true }

changelog/2529.added.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Add support for `libc::LOCAL_PEERTOKEN` in `getsockopt`.

src/sys/socket/mod.rs

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -499,6 +499,63 @@ cfg_if! {
499499
}
500500
}
501501

502+
cfg_if! {
503+
if #[cfg(apple_targets)] {
504+
use std::fmt;
505+
506+
/// Return type of [`LocalPeerToken`].
507+
///
508+
/// The audit token is an opaque token which identifies Mach tasks and
509+
/// senders of Mach messages as subjects to the BSM audit system. Only
510+
/// the appropriate BSM library routines should be used to interpret
511+
/// the contents of the audit token as the representation of the
512+
/// subject identity within the token may change over time.
513+
///
514+
/// Starting with macOS 11, almost all audit functions have been
515+
/// deprecated (see the system header `bsm/libbsm.h`), do not use them
516+
/// if your program target more recent versions of macOS.
517+
///
518+
/// [`LocalPeerToken`]: crate::sys::socket::sockopt::LocalPeerToken
519+
#[repr(C)]
520+
#[derive(Default, Copy, Clone, PartialEq, Eq, Hash)]
521+
pub struct audit_token_t {
522+
/// Value of the token.
523+
///
524+
/// This is considered an opaque value, do not rely on its format.
525+
pub val: [libc::c_uint; 8],
526+
}
527+
528+
// Make the debug representation a hex string to make it shorter and clearer.
529+
impl fmt::Debug for audit_token_t {
530+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
531+
f.debug_tuple("audit_token_t")
532+
.field(&format!("0x{:08X}", self))
533+
.finish()
534+
}
535+
}
536+
537+
impl fmt::LowerHex for audit_token_t {
538+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
539+
for v in self.val {
540+
fmt::LowerHex::fmt(&v, f)?;
541+
}
542+
543+
Ok(())
544+
}
545+
}
546+
547+
impl fmt::UpperHex for audit_token_t {
548+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
549+
for v in self.val {
550+
fmt::UpperHex::fmt(&v, f)?;
551+
}
552+
553+
Ok(())
554+
}
555+
}
556+
}
557+
}
558+
502559
feature! {
503560
#![feature = "net"]
504561
/// Request for multicast socket operations

src/sys/socket/sockopt.rs

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -563,7 +563,7 @@ sockopt_impl!(
563563
libc::SO_KEEPALIVE,
564564
bool
565565
);
566-
#[cfg(any(freebsdlike, apple_targets))]
566+
#[cfg(freebsdlike)]
567567
sockopt_impl!(
568568
/// Get the credentials of the peer process of a connected unix domain
569569
/// socket.
@@ -574,14 +574,34 @@ sockopt_impl!(
574574
super::XuCred
575575
);
576576
#[cfg(apple_targets)]
577+
sockopt_impl!(
578+
/// Get the credentials of the peer process of a connected unix domain
579+
/// socket.
580+
LocalPeerCred,
581+
GetOnly,
582+
libc::SOL_LOCAL,
583+
libc::LOCAL_PEERCRED,
584+
super::XuCred
585+
);
586+
#[cfg(apple_targets)]
577587
sockopt_impl!(
578588
/// Get the PID of the peer process of a connected unix domain socket.
579589
LocalPeerPid,
580590
GetOnly,
581-
0,
591+
libc::SOL_LOCAL,
582592
libc::LOCAL_PEERPID,
583593
libc::c_int
584594
);
595+
#[cfg(apple_targets)]
596+
sockopt_impl!(
597+
/// Get the audit token of the peer process of a connected unix domain
598+
/// socket.
599+
LocalPeerToken,
600+
GetOnly,
601+
libc::SOL_LOCAL,
602+
libc::LOCAL_PEERTOKEN,
603+
super::audit_token_t
604+
);
585605
#[cfg(linux_android)]
586606
sockopt_impl!(
587607
/// Return the credentials of the foreign process connected to this socket.

test/sys/test_sockopt.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,36 @@ pub fn test_local_peer_pid() {
6666
assert_eq!(pid, std::process::id() as _);
6767
}
6868

69+
#[cfg(apple_targets)]
70+
#[test]
71+
pub fn test_local_peer_token() {
72+
use nix::sys::socket::{audit_token_t, socketpair};
73+
74+
#[link(name = "bsm", kind = "dylib")]
75+
extern "C" {
76+
/// Extract the process ID from an `audit_token_t`, used to identify
77+
/// Mach tasks and senders of Mach messages as subjects of the audit
78+
/// system.
79+
///
80+
/// - `atoken`: The Mach audit token.
81+
/// - Returns: The process ID extracted from the Mach audit token.
82+
fn audit_token_to_pid(atoken: audit_token_t) -> libc::pid_t;
83+
}
84+
85+
let (fd1, _fd2) = socketpair(
86+
AddressFamily::Unix,
87+
SockType::Stream,
88+
None,
89+
SockFlag::empty(),
90+
)
91+
.unwrap();
92+
let audit_token = getsockopt(&fd1, sockopt::LocalPeerToken).unwrap();
93+
assert_eq!(
94+
unsafe { audit_token_to_pid(audit_token) },
95+
std::process::id() as _
96+
);
97+
}
98+
6999
#[cfg(target_os = "linux")]
70100
#[test]
71101
fn is_so_mark_functional() {

0 commit comments

Comments
 (0)