AF_UNIX Sockets and SCM_RIGHTS

AF_UNIX sockets are the transport layer for nearly all local IPC on Linux. Combined with SCM_RIGHTS for fd passing, they enable zero-copy data transfer between processes — the architecture that makes Wayland fundamentally different from X11.

AF_UNIX Sockets and File Descriptor Passing

Kernel Foundation

WAYLAND_DISPLAY=wayland-1 tells clients the socket filename inside XDG_RUNTIME_DIR. The full path is:

/run/user/1000/wayland-1

This is a Unix domain socket where the Wayland compositor (Hyprland, Sway, etc.) listens. Wayland uses AF_UNIX with SOCK_STREAM — reliable, ordered, bidirectional, like TCP but local and without network overhead.

Socket Types in AF_UNIX

Type Semantics Used By

SOCK_STREAM

Reliable, ordered byte stream (like TCP)

Wayland, D-Bus, PipeWire

SOCK_DGRAM

Unreliable, message-oriented (like UDP)

systemd journal, syslog

SOCK_SEQPACKET

Reliable, message-oriented (preserves boundaries)

Bluetooth HCI, some IPC protocols

The Critical Kernel Feature: SCM_RIGHTS

The kernel feature that makes Wayland fundamentally different from X11 is fd passing via SCM_RIGHTS:

// Simplified -- how a client sends a buffer to the compositor
struct msghdr msg;
struct cmsghdr *cmsg;
cmsg->cmsg_type = SCM_RIGHTS;  // "I'm passing a file descriptor"
sendmsg(wayland_fd, &msg, 0);

When wl-copy copies text to the clipboard:

  1. wl-copy connects to $XDG_RUNTIME_DIR/$WAYLAND_DISPLAY (the socket)

  2. Sends a Wayland protocol message offering the clipboard data

  3. When another app pastes, the compositor brokers an fd transfer — the pasting app gets a file descriptor it can read() from

The kernel’s SCM_RIGHTS mechanism (net/unix/af_unix.cunix_scm_to_skb()) enables zero-copy transfer. The compositor never copies the clipboard content itself — it passes file descriptors between processes. This is architecturally different from X11, where the X server held selection data in its own memory.

How fd Passing Works in the Kernel

  1. Sender calls sendmsg() with SCM_RIGHTS control message containing one or more file descriptors

  2. Kernel increments the reference count on each struct file being passed (fget())

  3. The fds are attached to the sk_buff (socket buffer) traveling through the AF_UNIX transport

  4. Receiver calls recvmsg() — kernel installs the struct file pointers into the receiver’s fd table (fd_install())

  5. The receiver now has its own fd pointing to the same underlying kernel object

The key insight: the file descriptors are not copied — the kernel object they reference is shared. Both processes end up with fds pointing to the same struct file, which points to the same inode or device. This is how DMA-BUF GPU buffers, shared memory regions, and clipboard data flow between processes without copying.

Kernel Source Map

Source File What It Does Key Functions

net/unix/af_unix.c

Socket connect/send/recv

unix_stream_connect(), unix_stream_sendmsg()

net/core/scm.c

SCM_RIGHTS implementation

scm_send(), scm_recv(), scm_detach_fds()

include/net/scm.h

Control message structures

struct scm_cookie, struct scm_fp_list

net/unix/scm.c

Unix-specific SCM helpers

unix_scm_to_skb(), unix_detach_fds()

Exploration Exercises

# Trace wl-copy's socket connection and fd passing
strace -e connect,sendmsg wl-copy <<< "test"

# See all AF_UNIX sockets on the system
ss -x

# Find which process owns the Wayland socket
ss -xlp | grep wayland

# Write a minimal AF_UNIX client in C (advanced)
# See: man 7 unix, man 2 socket, man 2 connect