Skip to main content

Crate unix_ancillary

Crate unix_ancillary 

Source
Expand description

Safe, ergonomic Unix socket ancillary data (SCM_RIGHTS fd passing).

This crate provides a safe Rust API for sending and receiving file descriptors over Unix domain sockets via SCM_RIGHTS.

§Design

  • No RawFd in the public APIOwnedFd and BorrowedFd only.
  • Automatic cleanup — received fds are OwnedFd, closed on drop.
  • No fd leaks on truncation — the high-level API sizes the receive cmsg buffer past every Unix kernel’s per-message fd cap, so the kernel cannot deliver more fds than we can wrap. Surplus fds beyond the caller’s N are wrapped in OwnedFd and closed automatically.
  • CLOEXEC errors are surfaced — on platforms without MSG_CMSG_CLOEXEC (notably macOS) we set FD_CLOEXEC post-recv; if that fails, every received fd is closed and the error is returned.

§Truncation safety

The high-level UnixStreamExt::recv_fds / UnixDatagramExt::recv_fds size the receive cmsg buffer to a platform-specific upper bound the kernel cannot exceed for a single SCM_RIGHTS message:

  • *Linux / BSD: fixed SCM_MAX_FD = 253. The peer’s kernel rejects oversized sends with EINVAL.
  • macOS: the receiver’s current RLIMIT_NOFILE, queried per recv call. The kernel must allocate an fd table entry per delivered fd and cannot exceed that limit.

Result: truncation is kernel-impossible. Every fd the kernel delivers becomes an OwnedFd we control. Surplus fds beyond the caller’s N are closed automatically. If the kernel still reports MSG_CTRUNC (defensive path; unreachable in practice), every fd we extracted is closed and an error is returned.

Low-level callers using SocketAncillary manage their own buffer and must size it appropriately — the is_truncated flag is exposed for that path.

§CLOEXEC race on macOS

macOS lacks MSG_CMSG_CLOEXEC on recvmsg. This crate sets FD_CLOEXEC via fcntl immediately after the syscall returns, but a concurrent fork+exec between the two can leak the fd into the child. If your workload forks concurrently with fd-receiving threads, hold a fork lock around the receive.

§Quick start

use std::os::unix::net::UnixStream;
use unix_ancillary::UnixStreamExt;

let (tx, rx) = UnixStream::pair().unwrap();

let file = std::fs::File::open("/dev/null").unwrap();
tx.send_fds(b"hello", &[&file]).unwrap();

let recv = rx.recv_fds::<1>().unwrap();
assert_eq!(&recv.data[..], b"hello");
assert_eq!(recv.fds.len(), 1);

Structs§

AncillaryError
Error returned when the ancillary buffer is too small.
Messages
Iterator over control messages in an ancillary buffer.
ReceivedFds
Result of a successful recv_fds call.
RecvResult
Result returned by cmsg_recvmsg.
ScmRights
Iterator over file descriptors received via SCM_RIGHTS.
SocketAncillary
Buffer for building and parsing Unix socket ancillary data (control messages).

Enums§

AncillaryData
Received ancillary data from a Unix socket.

Traits§

UnixDatagramExt
Extension trait for UnixDatagram adding fd-passing convenience methods.
UnixStreamExt
Extension trait for UnixStream adding fd-passing convenience methods.

Functions§

cmsg_recvmsg
Receive data with ancillary control messages from a Unix socket.
cmsg_sendmsg
Send data with ancillary control messages over a Unix socket.