Skip to content

Archive

Linux

205 articles
Software Engineering 18 Sep 2026 4 min read

CLOSE_RANGE_UNSHARE Isolates Descriptor Table Cleanup

A thread preparing to cross an execve() boundary can need to remove every file descriptor above a small preserved set while other threads still share its descriptor table. Closing descriptors one by one creates a race: another thread can allocate a descriptor into the interval while cleanup is in progress. Linux close_range() with CLOSE_RANGE_UNSHARE changes the table-sharing boundary before applying the range operation. This behavior matters because a file descriptor number is only an index into a process descriptor table. With CLONE_FILES, multiple tasks can refer to the same table, so a close performed through one task changes descriptor visibility for all tasks sharing it. CLOSE_RANGE_UNSHARE gives the calling task a private descriptor table as part of the operation.

Linux 18 Sep 2026 6 min read

close_range Controls Descriptor Inheritance Across exec Boundaries

A process preparing to call execve() may have hundreds or thousands of open file descriptors, while the new program should inherit only a small selected set. Closing descriptors one by one creates both bookkeeping cost and a concurrency problem: another thread can allocate a descriptor while the cleanup loop is still running. Linux close_range() moves that operation to the descriptor-table boundary. A caller specifies an inclusive numeric range and asks the kernel either to close descriptors in that range or mark them close-on-exec. With CLOSE_RANGE_UNSHARE, the caller can first detach its descriptor table from threads or processes that share it.

Software Engineering 17 Sep 2026 6 min read

userfaultfd Moves Missing-Page Resolution into User Space

A thread can touch a valid virtual address and stop before the access completes because the page has no present backing yet. With a range registered in UFFDIO_REGISTER_MODE_MISSING, Linux can report that fault through userfaultfd instead of resolving it entirely inside the kernel. A user-space manager then decides which page contents become visible before the blocked access resumes. This changes the ownership of one part of page-fault handling. The kernel still detects the fault, validates the virtual memory area, blocks the faulting execution, and installs mappings through the UFFDIO_* interface. User space gains control over the content and timing of resolution for registered faults.

Cybersecurity 17 Sep 2026 7 min read

Unix Socket Peer Credentials Bind Identity to a Local Connection

Unix Socket Peer Credentials Bind Identity to a Local Connection A privileged local service often accepts requests from processes that share the same host but do not share the same authority. A pathname on a Unix domain socket can control who reaches the listener, yet a successful connection does not by itself tell the service which process is on the other end. Linux provides a second boundary: SO_PEERCRED lets a connected Unix socket expose peer credentials supplied by the kernel.

Linux 17 Sep 2026 4 min read

Truncating a Mapped File Can Trigger SIGBUS

A process can retain a valid mmap() address range after another operation shrinks the backing file, then receive SIGBUS when it touches a mapped page past the file’s new end. The mapping itself has not vanished. Its backing object no longer covers every page that the virtual mapping originally referenced. This boundary is easy to miss because mapping lifetime and file size are separate state. Closing the original file descriptor does not invalidate an established mapping, and shrinking the file does not act like munmap() on every process that maps it.

Software Engineering 17 Sep 2026 4 min read

timerfd Counts Expirations Through Descriptor Reads

A periodic timerfd can expire several times before user space reads it. The next successful read() does not report only the most recent tick: it returns an unsigned 64-bit count of expirations accumulated since the previous successful read, or since the timer was configured if no read has completed yet. That behavior makes a timer an event-loop object without converting each expiration into a signal. The descriptor becomes readable when at least one expiration is pending, and the same descriptor can participate in poll(), select(), or epoll() beside sockets, pipes, and other descriptor-backed event sources.

Linux 17 Sep 2026 5 min read

TCP_NODELAY Disables Nagle Coalescing on a Socket

A TCP socket can hold a small write instead of transmitting it immediately when earlier data remains unacknowledged. This behavior comes from Nagle coalescing: it limits the stream of small TCP segments by allowing outstanding data to influence transmission of newly queued bytes. On Linux, setting TCP_NODELAY disables that coalescing rule for the socket. Small writes become eligible for prompt transmission, subject to the rest of the TCP stack, congestion control, flow control, queue state, and device scheduling.

Software Engineering 17 Sep 2026 6 min read

SO_REUSEPORT Moves TCP Connection Distribution Into the Kernel

With SO_REUSEPORT, several Linux TCP sockets can listen on the same local address and port at the same time. Incoming connections are assigned to a member of that reuseport group before an application calls accept(). The application no longer needs one shared listening socket as the sole handoff point between the network stack and multiple workers. That changes more than bind eligibility. It moves connection distribution into the kernel and gives each listener its own socket identity and accept path. The resulting architecture has different queueing, lifecycle, and routing properties from a design in which many workers compete on one listening socket.

Software Engineering 17 Sep 2026 4 min read

SO_REUSEPORT Forms Kernel-Selected Socket Groups

Multiple Linux sockets can bind the same local address when every participating socket enables SO_REUSEPORT before bind(). Incoming traffic is then assigned to a member of the resulting reuseport group rather than delivered to every socket. The shared address is therefore a kernel selection boundary, not a broadcast endpoint. This behavior supports independent receive or accept loops without forcing all work through one listening descriptor. It also creates a distinct operational property: group membership and the selection policy determine which socket receives a packet or connection.

Linux 17 Sep 2026 6 min read

SO_REUSEPORT Distributes Traffic Across Socket Groups

SO_REUSEPORT changes a local endpoint from a single-socket binding into a socket group. On Linux, multiple TCP or UDP sockets can bind the same local address when every participating socket enables the option before bind() and the bind credentials satisfy the kernel’s reuse rules. That behavior is distinct from merely relaxing address-conflict checks. Incoming traffic must also be assigned to one member of the group. The resulting selection boundary affects listener architecture, queue isolation, process restarts, UDP flow placement, and any design that assumes a port maps to exactly one socket.

Linux 17 Sep 2026 4 min read

SO_RCVLOWAT Raises the Readability Threshold for Linux Sockets

A Linux socket with SO_RCVLOWAT set above one byte can have data queued while poll(), select(), or epoll still reports no normal readable readiness. Since Linux 2.6.28, those readiness interfaces respect the configured receive low-water mark. The option changes the threshold associated with normal receive readiness. It does not define message boundaries, reserve receive-buffer space, or guarantee that a later receive operation returns exactly the configured number of bytes. Readability can require more than one queued byte Socket receive readiness is usually observed with the default low-water mark of one byte. In that state, ordinary queued data is enough to satisfy the data-volume part of the readable condition.

Software Engineering 17 Sep 2026 5 min read

signalfd Turns Pending Signals into Readable Records

A signal included in a signalfd mask can make a file descriptor readable instead of invoking an asynchronous handler, provided that signal is blocked from ordinary delivery. A successful read() then consumes pending signal state and returns one or more signalfd_siginfo records. This changes the interface used to receive selected signals, but it does not replace Linux signal semantics. Signal masks, process-directed versus thread-directed delivery, standard-signal coalescing, and the special status of SIGKILL and SIGSTOP still define the boundary around the descriptor.

Software Engineering 17 Sep 2026 5 min read

signalfd Consumes Blocked Signals Through Descriptor Reads

A Linux signalfd becomes readable when a signal selected by its mask is pending for the reading context. A successful read() does more than observe that state: it consumes the returned signal occurrences, removing them from pending signal state. That behavior gives signals a descriptor-facing consumption path. It does not convert the signal subsystem into a byte stream, and it does not replace the signal mask that controls ordinary delivery.

Cybersecurity 17 Sep 2026 6 min read

SCM_RIGHTS Transfers File-Descriptor Authority Across Unix Sockets

SCM_RIGHTS Transfers File-Descriptor Authority Across Unix Sockets A privileged service can open a file that another process could not open by pathname, then pass that access through a Unix-domain socket. The receiving process gets a new file descriptor referring to the same kernel open-file state. No second pathname lookup is required, and the receiver’s ability to open that path is not re-evaluated as part of the transfer. That property makes SCM_RIGHTS more than an IPC convenience. It moves an already-established kernel capability across a process boundary. Security therefore depends on both sides of the exchange: the sender must constrain which descriptors can leave its authority domain, and the receiver must treat incoming descriptors as privileged objects whose properties require validation.

Software Engineering 17 Sep 2026 4 min read

renameat2 RENAME_EXCHANGE Swaps Two Paths in One Filesystem Operation

renameat2() with RENAME_EXCHANGE changes two existing directory entries as one atomic rename operation. Before the call, each pathname reaches its original object; after a successful call, each pathname reaches the object formerly named by the other path. There is no successful intermediate state in which one of the two names has merely been removed or overwritten. That property is distinct from ordinary rename(). A conventional rename can atomically replace a destination, but replacement discards the destination name from the namespace. Exchange preserves both named objects and swaps their positions.

Linux 17 Sep 2026 5 min read

rename Replaces a Directory Entry Atomically on Linux

A successful rename() can replace an existing destination pathname without exposing an intermediate state in which that destination name is missing. Processes resolving the destination observe either the old directory entry or the replacement, subject to filesystem and mount constraints. That atomic namespace transition is narrower than several properties often associated with file replacement. It does not make prior writes durable, does not force directory metadata to stable storage, and does not invalidate file descriptors that already refer to the replaced file.

Software Engineering 17 Sep 2026 4 min read

pidfd Keeps Process Identity Stable Across PID Reuse

A numeric Linux PID can be reused after its process exits. A PID file descriptor instead refers to a specific task, so later operations through that descriptor do not silently retarget a different process that receives the same numeric PID. This changes process identity from a lookup repeated at each operation into a kernel-held reference with descriptor semantics. The distinction matters for signaling, exit monitoring, and event loops that retain process handles across asynchronous work.

Cybersecurity 17 Sep 2026 5 min read

openat2 Makes Path-Resolution Policy Part of the Open

openat2 Makes Path-Resolution Policy Part of the Open A service receives a relative pathname and intends to open only objects below a directory it already trusts. A lexical check can reject obvious .. components, yet the filesystem namespace may contain symbolic links, mount points, or concurrent renames that change the path walk after that check. The security decision and the file open then describe two different moments. Linux openat2() provides a narrower boundary. Its resolve flags constrain the kernel’s path-resolution operation that produces the file descriptor. The mechanism does not make arbitrary path handling safe, but it can move several confinement rules from preflight string logic into the lookup that actually selects the object.

Software Engineering 17 Sep 2026 5 min read

openat2 Constrains Path Resolution at the Lookup Boundary

A pathname can begin below a trusted directory and still escape that subtree during resolution. A .. component, symbolic link, magic link, or mount transition can change the object ultimately reached even when the initial directory file descriptor is trusted. Linux openat2() places constraints inside pathname resolution itself, so the kernel can reject a lookup that violates the selected boundary. This differs from checking a pathname string before calling open(). Path resolution operates on filesystem objects and namespace state, not only text. openat2() extends the openat() model with a struct open_how whose resolve field controls traversal of pathname components.

Linux 17 Sep 2026 4 min read

O_CLOEXEC Closes Descriptors Atomically Across exec

A file descriptor created without close-on-exec state can escape into a newly executed program during a narrow concurrency window. In a multithreaded Linux process, setting FD_CLOEXEC with a later fcntl() call leaves that window open between descriptor creation and the flag update. O_CLOEXEC removes the split operation. The kernel creates the descriptor with its close-on-exec flag already set, so another thread cannot observe an intermediate state in which the descriptor exists but remains inheritable across a successful execve().

Linux 17 Sep 2026 5 min read

O_APPEND Couples End Positioning with Each Write

O_APPEND changes a write from two separable actions into one coupled operation: Linux positions the open file description at the current end of the file and performs the write as a single atomic step. That property matters when multiple writers target one regular file. A sequence built from lseek(fd, 0, SEEK_END) followed by write(fd, ...) does not carry the same append semantics because another writer can change the file between those two system calls.

Cybersecurity 17 Sep 2026 5 min read

no_new_privs Makes Exec-Time Privilege Gain Irreversible

no_new_privs Makes Exec-Time Privilege Gain Irreversible A Linux service may deliberately execute programs that carry set-user-ID bits or file capabilities while intending to remain at its existing privilege level. Without an explicit execution boundary, execve() can be a privilege transition: metadata on the executable may change effective credentials or contribute capabilities to the new program. The no_new_privs task attribute changes that transition. Once set, a successful execve() cannot grant the task privilege that it could not exercise before the call. The attribute is inherited by descendants, survives execution, and cannot be cleared. Those properties make it a one-way constraint on a process lineage rather than a temporary option around one executable.

Software Engineering 17 Sep 2026 4 min read

memfd Seals Turn Shared Files into Monotonic Objects

A Linux memfd can begin as a writable anonymous file and later acquire restrictions that cannot be removed. The restrictions belong to the inode, so transferring or duplicating a descriptor does not create a less restricted view. Once a seal is added successfully, every descriptor referring to that inode is subject to it. This makes sealing different from descriptor access modes. A descriptor can carry local flags, while a seal changes the mutation boundary of the shared file object itself.

Software Engineering 17 Sep 2026 6 min read

Linux userfaultfd Turns Page Faults Into a Userspace Protocol

A thread can access a valid virtual address and stop before that access completes because another userspace component has been given responsibility for resolving the page fault. With Linux userfaultfd, selected memory ranges can turn faults into descriptor messages while the faulting thread remains blocked until an appropriate resolution operation makes progress possible. This is not a replacement for the kernel’s virtual-memory subsystem. The kernel still detects the fault, validates the registered range, blocks the affected execution path, and performs the page-table operation requested by the manager. The unusual boundary is that userspace can participate in deciding when and with what contents a fault is resolved.