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:

DescriptorNameDefault destination
0STDINkeyboard / input stream
1STDOUTterminal / output stream
2STDERRterminal / 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 footholdcat (and its pager cousins) is the canonical first tool; see cat for the useful flags and the SUID angle.

Sources