UNIX File Descriptors
A file descriptor is a non-negative integer that a process uses to identify an open file, pipe, socket, or device. Every UNIX process starts life with three of them already open:
| Descriptor | Name | Default destination |
|---|---|---|
| 0 | STDIN | keyboard / input stream |
| 1 | STDOUT | terminal / output stream |
| 2 | STDERR | terminal / error stream |
These three are the bedrock of shell redirection. When you write command > file 2>&1, you are explicitly manipulating descriptors 1 and 2.
Ad-hoc descriptors
Bash and other POSIX shells let you create additional descriptors at runtime:
# Open descriptor 3 for reading and writing to a file
exec 3<> /tmp/data
# Read from it
read -u 3 line
# Close it
exec 3>&-This is useful for locking files, creating bidirectional pipes, or preserving output streams when a subshell or sudo would otherwise swallow them.
Security relevance
- Reverse shells often close or redirect descriptors 0, 1, and 2 to detach from a terminal — see shell-stabilization.
- Port scanning with Bash uses
/dev/tcp/$IP/$PORT, which is implemented as a file descriptor abstraction over TCP — see bash-port-scanning. - File descriptor exhaustion is a classic DoS vector; each open socket or file consumes a descriptor, and the per-process limit (
ulimit -n) is finite. - Reading files on a foothold —
cat(and its pager cousins) is the canonical first tool; see cat for the useful flags and the SUID angle.