Skip to content

Archive

Linux

205 articles
Linux 18 Sep 2026 5 min read

userfaultfd Turns Page Faults into Userspace Events

A thread can fault on a virtual address and remain blocked while another userspace thread or process decides what page state should make that access continue. userfaultfd provides this boundary by turning selected page faults into messages on a file descriptor and pairing those messages with ioctls that resolve the fault. The mechanism does not replace the kernel page-fault machinery. It inserts userspace control at registered ranges and fault classes, while the kernel still owns page tables, fault blocking, and the transition that makes the page usable again.

Cybersecurity 18 Sep 2026 6 min read

UNIX Socket Peer Credentials Bind Local IPC to Kernel-Observed Identity

A privileged local daemon accepts a request over an AF_UNIX socket and needs to decide whether the sender may perform an operation. Trusting a UID, PID, or account name encoded inside the request merely trusts data supplied by the client. Linux provides a different identity channel: the kernel can expose credentials associated with the peer or with an individual message. SO_PEERCRED and SCM_CREDENTIALS both carry a struct ucred, but they describe different moments in an IPC relationship. Treating them as interchangeable can turn a sound local authorization boundary into a stale-identity assumption.

Software Engineering 18 Sep 2026 5 min read

timerfd Turns Timer Expirations into Descriptor Readiness

A timerfd becomes readable after its timer expires. The notification is not a signal handler invocation and not a byte-stream message. Linux records pending expirations on a timer object and exposes that state through a file descriptor, so a timer can occupy the same readiness boundary as sockets, pipes, and other descriptors. That interface does more than replace one notification mechanism with another. Clock selection determines the time domain, arming flags determine whether a deadline is relative or absolute, and each successful read reports the number of expirations accumulated since the preceding successful read or timer reconfiguration.

Software Engineering 18 Sep 2026 4 min read

timerfd Turns Timer Expiration Counts into Pollable Descriptor State

A Linux timerfd becomes readable when its configured timer has expired. The bytes returned by read(2) are not a timestamp or event record: they encode one unsigned 64-bit integer containing the number of expirations since the previous successful read. Timer state therefore participates in the same readiness machinery as sockets and pipes while retaining timer-specific semantics behind the descriptor boundary. Readiness represents a pending expiration count timerfd_create(2) creates a descriptor associated with a clock, while timerfd_settime(2) arms or disarms its timer. Once at least one expiration is pending, poll(2), select(2), and epoll(7) can report the descriptor as readable.

Linux 18 Sep 2026 4 min read

timerfd Counts Expirations Through Descriptor I/O

A periodic timerfd does not require one userspace wakeup for every timer expiration. If several expirations occur before the descriptor is read, Linux accumulates them and returns the count in one 8-byte integer. That behavior makes timer state fit the same readiness model used for sockets, pipes, and other descriptors. It also gives delayed event loops explicit information about missed periods rather than collapsing several expirations into one notification. Expiration state becomes readable descriptor data timerfd_create() creates a timer object and returns a file descriptor referring to it. The selected clock defines the timer’s time base. Common choices include CLOCK_MONOTONIC, CLOCK_REALTIME, and CLOCK_BOOTTIME.

Software Engineering 18 Sep 2026 5 min read

SO_REUSEPORT Moves Listener Distribution into Socket Selection

SO_REUSEPORT permits multiple Linux AF_INET or AF_INET6 sockets to bind the same local address and port when every member satisfies the reuse-port rules. For TCP listeners, this moves incoming connection distribution ahead of accept(): the kernel selects a listener from the reuse-port group, and that listener receives the connection on its accept queue. For UDP, selection determines which socket receives an incoming datagram. This is a different concurrency boundary from several threads sharing one listening file description. Each reuse-port member is a distinct socket, with its own descriptor, queues, polling state, and lifecycle.

Software Engineering 18 Sep 2026 3 min read

signalfd Routes Pending Signals Through Descriptor I/O

A Linux signalfd becomes readable when a signal selected by its mask is pending for the reading context. A successful read(2) consumes pending signal state and returns one or more fixed-size signalfd_siginfo records. Signal handling can therefore enter a descriptor-driven event loop without turning asynchronous handlers into the primary dispatch mechanism. The descriptor mask does not block signals The mask passed to signalfd(2) selects signals that the descriptor can accept. It does not modify the calling thread’s signal mask. Normal use separately blocks those signals with sigprocmask(2) or pthread_sigmask(3) so their ordinary dispositions do not run before descriptor consumption.

Linux 18 Sep 2026 5 min read

Seccomp User Notifications Delegate Selected System Calls to a Supervisor

A seccomp filter can stop a selected system call before execution and turn it into a request on a listener file descriptor. The calling thread remains blocked while a userspace supervisor examines the notification and returns a result. This creates a mediation boundary that is narrower than tracing every system call and more dynamic than encoding every decision directly in classic BPF. The mechanism is SECCOMP_RET_USER_NOTIF. A filter returns that action for operations that require external mediation. A filter installed with SECCOMP_FILTER_FLAG_NEW_LISTENER yields a listener file descriptor, and a supervisor uses seccomp notification ioctls on that descriptor.

Software Engineering 18 Sep 2026 6 min read

seccomp User Notification Delegates Selected Syscalls to a Supervisor

seccomp User Notification Delegates Selected Syscalls to a Supervisor A seccomp filter can stop a selected system call before the kernel executes it and emit a notification to a user-space supervisor instead. The target thread remains blocked while the supervisor receives the event and returns a disposition. This behavior turns a filter result into a controlled handoff across the kernel/user-space boundary. The mechanism is SECCOMP_RET_USER_NOTIF. It differs from ordinary seccomp actions because the BPF filter does not finish the decision by itself. A listener file descriptor becomes the coordination point for notification receipt, response delivery, and optional file-descriptor injection.

Software Engineering 18 Sep 2026 6 min read

SCM_RIGHTS Transfers Open File Descriptions Across Process Boundaries

SCM_RIGHTS lets one process send a reference to an open file through a Unix domain socket. The receiver obtains a file descriptor in its own descriptor table, but the transfer does not reopen the pathname or copy the kernel object. On Linux, the resulting reference has semantics equivalent to duplicating the sender’s descriptor into the receiving process. That distinction matters whenever a process boundary is also an authority boundary. A supervisor can open a socket, file, pipe, device, or other descriptor-backed object and pass the established reference to a worker. The worker receives access to the already-open object, including open-file state that can remain shared with the sender.

Linux 18 Sep 2026 4 min read

process_madvise Applies Memory Reclaim Advice Across Process Boundaries

process_madvise() can make one Linux process request memory-management action for virtual-address ranges owned by another process. The target is identified by a pidfd, while an iovec array names the target ranges. This separates memory-policy decisions from the process whose mappings receive the advice. The interface is useful for controllers that already have external knowledge about workload state. A runtime manager can mark inactive memory cold or request page reclamation without injecting code into the managed process. That capability is bounded by permission checks, supported advice values, and partial-progress semantics.

Software Engineering 18 Sep 2026 4 min read

pidfds Bind Process Operations to Stable Kernel References

A numeric PID names a process only while that PID remains assigned to it. After termination and reaping, Linux can reuse the number for another process. A PID file descriptor, or pidfd, instead holds a kernel reference to a specific task, so later operations can target that task without resolving its numeric PID again. This distinction removes a class of time-of-check/time-of-use races from process management. It does not make a process immortal, grant extra permissions, or turn every process operation into a portable descriptor API.

Cybersecurity 18 Sep 2026 6 min read

pidfds Bind Process Operations to Stable Kernel References

A supervisor records PID 4127, performs unrelated work, then sends a signal to 4127. Between those steps, the original process can exit and the kernel can eventually assign the same numeric PID to another process. The integer still names a process, but not necessarily the process that the supervisor intended to affect. Linux PID file descriptors, commonly called pidfds, move that boundary from repeated numeric lookup to a file descriptor that refers to a particular task. That change is narrow but security-relevant: operations that accept a pidfd can stay bound to the task selected when the reference was acquired rather than resolving a reusable number again.

Linux 18 Sep 2026 6 min read

pidfd_getfd Duplicates Another Process File Descriptor into the Caller

A file descriptor number has meaning only inside its process descriptor table, but the kernel object behind that number can be shared across processes. Linux pidfd_getfd() bridges those two scopes: it takes a PID file descriptor plus a descriptor number from the referenced process and installs a duplicate descriptor in the caller. The new descriptor refers to the same open file description as the target descriptor. That last property is the central boundary. pidfd_getfd() does not reopen a pathname, copy bytes, or create an independent file position. It duplicates an existing kernel reference and therefore inherits sharing semantics that can affect both processes.

Linux 18 Sep 2026 5 min read

openat2 Resolve Flags Constrain Path Traversal per Open

A pathname passed to openat2() can be rejected even when the same pathname would resolve successfully through openat(). The difference comes from open_how.resolve: Linux can apply traversal constraints while resolving every component of that single open operation. This changes the boundary around path handling. A directory file descriptor can act as more than a starting point; resolve flags can restrict escapes, symbolic-link traversal, mount crossings, and lookups that require work beyond cached state.

Cybersecurity 18 Sep 2026 5 min read

openat2 Resolution Flags Constrain Path Traversal at the Kernel Boundary

A service can validate a pathname and still open a different object if the namespace changes between validation and use. Symbolic links, mount topology, rename operations, and special procfs links make pathname resolution a kernel operation with state that can change concurrently. Linux openat2() addresses part of this boundary by attaching resolution constraints to the lookup that produces the file descriptor. The security property is narrower than generic path sanitization. openat2() does not declare a pathname safe. It lets a caller ask the kernel to reject specific resolution behavior while the kernel performs the walk.

Software Engineering 18 Sep 2026 5 min read

openat2 Constrains Path Resolution Inside a Directory Boundary

A pathname is not a stable object reference. Between its starting directory and final component, Linux path resolution may follow symbolic links, cross mount points, process .., or encounter special links exposed by pseudo-filesystems. openat2() lets a caller attach constraints to that resolution operation so the kernel can reject a lookup that leaves the intended boundary. The distinction is stronger than checking a normalized string before open(). String validation examines syntax. openat2() can constrain the kernel’s actual traversal while filesystem objects and mount topology participate in the lookup.

Linux 18 Sep 2026 5 min read

mseal Locks Memory Mapping Layout and Permissions

A process can establish a memory mapping with the intended address, size, and protection bits, then later alter that mapping with operations such as munmap(), mprotect(), or mremap(). Linux mseal() adds a one-way state transition: selected virtual memory areas can be sealed so a class of later mapping modifications is rejected by the kernel. The mechanism protects mapping structure rather than the bytes stored in the mapping. A writable sealed mapping remains writable through ordinary stores. Sealing instead constrains operations that could remove the mapping, relocate it, replace it, or change attributes covered by the sealing rules.

Software Engineering 18 Sep 2026 4 min read

memfd Seals Turn Shared File State into Monotonic Restrictions

A memfd_create() file can begin as writable shared state and later become progressively more constrained. File seals make that transition monotonic: successful seals are properties of the inode, affect every descriptor referring to it, and cannot be removed. That property is useful when one process prepares bytes and then transfers a descriptor to another process. The receiver can inspect kernel-enforced restrictions instead of relying only on a protocol promise that the producer has stopped changing the object.

Cybersecurity 18 Sep 2026 6 min read

memfd File Seals Turn Shared Memory into a Kernel-Enforced Mutation Boundary

A broker can allocate a memory-backed object, populate it, and pass its file descriptor to another process over a UNIX domain socket. The receiver may treat the bytes as immutable configuration, compiled code, or a serialized artifact. That assumption is unsafe if the sender or another holder can still alter the same inode after validation. Linux memfd_create() and file seals provide a kernel-enforced way to narrow that mutation surface without assigning the object a persistent filesystem pathname.

Linux 18 Sep 2026 6 min read

membarrier Moves Memory-Ordering Cost to an Infrequent Coordination Path

A full hardware memory barrier in a frequently executed path can impose a cost on every operation, even when cross-thread coordination happens only occasionally. Linux membarrier() supports a different placement of that cost: a rare coordination path can request an ordering event across a defined set of threads while a frequent path may need only compiler-level ordering. This is not a general replacement for atomics, locks, or the memory model of a programming language. It is a Linux-specific synchronization primitive for designs whose correctness already has a precise pairing between a frequent path and an infrequent coordination path.

Software Engineering 18 Sep 2026 8 min read

MAP_SHARED mmap Couples Memory Writes to File-Backed Page State

A writable MAP_SHARED mapping lets a process modify file-backed state with ordinary memory stores. The bytes are addressed through virtual memory rather than passed to write(), but the mapping still participates in filesystem state: modifications can become visible through other shared mappings and file I/O, and dirty pages can later be written back to storage. That interface compresses several mechanisms into one address range. CPU stores, page faults, page-cache residency, filesystem writeback, and storage persistence can all participate in the lifetime of the same bytes. Treating a successful store as equivalent to durable file output collapses boundaries that the operating system keeps distinct.

Software Engineering 18 Sep 2026 6 min read

Linux userfaultfd Moves Selected Page Fault Handling into User Space

A page fault normally crosses from a process into the kernel and returns only after the kernel has resolved the virtual-memory condition or delivered an error. Linux userfaultfd can insert a user-space component into that path for explicitly registered address ranges. The kernel reports selected faults through a file descriptor, blocks the faulting execution context when the mode requires it, and accepts an ioctl that resolves the fault. This is a Linux virtual-memory interface, not a C or POSIX memory guarantee. Its behavior depends on negotiated kernel features, the registered range, its mapping type, and the registration mode.

Software Engineering 18 Sep 2026 7 min read

Linux splice Makes Pipe Capacity Part of Data-Transfer Semantics

Linux splice() can transfer bytes between file descriptors without routing those bytes through a user-space buffer, but the interface is not a generic descriptor-to-descriptor copy primitive. At least one endpoint must be a pipe. That requirement makes pipe state part of the transfer contract: capacity, readable data, writer presence, blocking mode, and partial progress can all affect an otherwise straightforward data path. The useful boundary is therefore not simply “kernel copy versus user copy.” splice() changes the shape of ownership and flow control. Application code stops owning an intermediate byte array, while it still owns the control loop that accounts for bytes transferred, handles readiness, and preserves offset semantics.