Skip to content

Archive

File Descriptors

35 articles
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().

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 5 min read

Linux pidfd Binds Process Identity to a File Descriptor

A numeric PID is a name from a reusable kernel namespace. Once a process exits and its PID becomes available for reuse, a later process can receive the same number. Linux pidfds add a different form of reference: a file descriptor tied to a specific task rather than a number that must be resolved again at each operation. That distinction changes the boundary between process discovery and later process control. A program can resolve a PID once with pidfd_open(), retain the resulting descriptor, and use pidfd-aware interfaces without treating the numeric PID as permanent identity.

Software Engineering 17 Sep 2026 6 min read

Linux O_TMPFILE Keeps Staging Files Out of the Namespace

Linux O_TMPFILE creates a regular file without first placing a name for that file in a directory. The caller receives a file descriptor and can write data, set metadata, or abandon the object while no pathname exposes the partially prepared file. If publication is required, a later link operation can attach a directory entry to the same inode. This separates object construction from namespace publication. It does not make every surrounding filesystem operation transactional, and it does not provide replacement semantics for an existing destination. Its useful boundary is narrower: intermediate file state can remain reachable only through open references until the process explicitly creates a name.

Cybersecurity 17 Sep 2026 5 min read

execveat Binds Program Execution to an Open File Reference

A launcher selects an executable from a directory, checks attributes or content, and then starts it. If selection and execution each resolve the pathname independently, a rename, symlink change, or directory replacement between those operations can make the executed object differ from the object that was checked. Linux execveat() can move that boundary from a second pathname lookup to an already acquired file reference. With AT_EMPTY_PATH, an empty pathname tells the kernel to execute the object referred to by dirfd. That descriptor may have been opened with O_PATH. The execution decision still passes through normal kernel permission and executable-format checks, but object selection no longer depends on resolving the original pathname again.

Linux 17 Sep 2026 4 min read

Duplicated File Descriptors Share an Open File Description

Two file descriptor numbers can move the same file offset. On Linux, this occurs when both descriptors refer to one open file description, as happens after dup() and across inherited descriptors after fork(). The distinction matters because a file descriptor is a process-visible integer, while the open file description is the kernel object that carries state for an open instance of a file. Treating those layers as interchangeable can produce offset interference, status-flag changes that cross descriptor boundaries, and surprising behavior after process creation.

Cybersecurity 17 Sep 2026 5 min read

Close-on-Exec Makes Descriptor Inheritance an Explicit Boundary

A service opens a privileged socket, starts helper programs, and expects those helpers to receive only standard input, output, and error. One descriptor created without close-on-exec can quietly violate that boundary. If it remains present when a new program image is installed, the helper inherits access to the kernel object even when its own credentials could never have opened that object. Linux treats this as descriptor inheritance, not a new authorization event. The security decision made when the object was opened is embodied in the descriptor. FD_CLOEXEC controls whether that established authority crosses a successful execve().

Cybersecurity 17 Sep 2026 5 min read

close_range with UNSHARE Detaches Descriptor Tables Before Bulk Closure

A multithreaded Linux process can reach an awkward boundary just before execve(): one thread wants to discard every file descriptor above standard input, output, and error, while another thread can still create descriptors in the same table. A loop of close() calls treats descriptor numbers individually, but it does not by itself change the fact that the table is shared. close_range() with CLOSE_RANGE_UNSHARE addresses that specific race. The kernel first gives the caller a file descriptor table that is no longer shared with the other users of the old table, then applies the requested bulk closure to the caller’s table. The security property is about table ownership during cleanup, not merely fewer system calls.

Linux 16 Sep 2026 5 min read

io_uring Registered Files Bypass Repeated Descriptor Lookup

An io_uring request that uses a normal file descriptor still has to resolve that descriptor through the submitting task’s file table. A registered file takes a different path: the ring holds a reference to the open file, and an SQE names a slot in that ring-local table. That distinction removes repeated descriptor lookup from the request path. It also changes resource lifetime, update semantics, and the meaning of the SQE fd field.

Linux 05 Sep 2026 12 min read

Pass Open File Descriptors Between Linux Processes with SCM_RIGHTS

Processes often need to hand each other access to an already-open resource. A supervisor may accept a client connection and delegate it to a worker. A privileged helper may open a protected file, then give an unprivileged process access without revealing broader filesystem permissions. A service may create an anonymous in-memory file and transfer it to another process. Sending the integer value of a file descriptor does not solve this problem. File descriptor numbers are meaningful only inside one process’s descriptor table. Descriptor 7 in one process can refer to a socket while descriptor 7 in another process refers to an unrelated file.

Linux 02 Sep 2026 4 min read

Diagnosing File Descriptor Leaks on Linux with procfs

A Linux process uses file descriptors for more than ordinary files. Network sockets, pipes, event descriptors, terminals, and many other kernel objects appear through the same integer-based interface. When a service slowly accumulates descriptors, it may eventually fail with Too many open files, stop accepting connections, or behave unpredictably under load. Linux procfs provides enough information to investigate many descriptor leaks without installing extra tools. Start by counting descriptors For a known process ID: