Skip to content

Unix Filesystem Cheat Sheet

Filesystem core concepts: directory layout, inode metadata, permissions, links, file descriptors, and common security pitfalls.

Standard directory layout for Unix-like systems.

DirectoryPurposeExamples
/Root filesystemMust boot and recover from here
/binEssential user binariesls, cp, cat
/sbinEssential system binariesinit, mount, fsck
/etcHost-specific configurationpasswd, fstab, hosts
/varVariable data (survives reboot)/var/log, /var/tmp
/tmpTemporary (cleared on reboot)Session data
/homeUser home directories/home/alice
/rootRoot user’s home
/usrSecondary hierarchy (shareable)Distro-installed software
/usr/localLocally installed softwareAdmin-installed programs
/optAdd-on application packagesThird-party software
/srvData for servicesWeb server files
/runRuntime variable dataPID files, sockets
MountTypePurpose
/devdevtmpfsDevice nodes (udev managed)
/procprocfsProcess and kernel info
/syssysfsDevice and driver info
/tmptmpfsRAM-backed temporary storage
/runtmpfsRuntime data (cleared on reboot)
Terminal window
/proc/PID/cmdline # Command line arguments
/proc/PID/cwd # Symlink to current working directory
/proc/PID/exe # Symlink to executable
/proc/PID/fd/ # Open file descriptors
/proc/PID/maps # Memory mappings
/proc/PID/status # Human-readable status
/proc/PID/environ # Environment variables
/proc/cpuinfo # CPU information
/proc/meminfo # Memory statistics
/proc/mounts # Mounted filesystems
Terminal window
/sys/block/ # Block devices
/sys/class/ # Device classes (net, tty, etc.)
/sys/devices/ # Device hierarchy
/sys/fs/ # Filesystem information
DevicePurpose
/dev/nullDiscards writes, reads EOF
/dev/zeroReads return zeros
/dev/randomBlocking random generator
/dev/urandomNon-blocking random
/dev/stdinSymlink to /proc/self/fd/0
/dev/stdoutSymlink to /proc/self/fd/1
/dev/stderrSymlink to /proc/self/fd/2
/dev/ttyControlling terminal

An inode stores file metadata—everything except the filename:

FieldDescriptionAccessed via
Device IDFilesystem hosting the inodestat.st_dev
Inode numberUnique ID within filesystemstat.st_ino
File typeRegular, directory, symlink, etcstat.st_mode
Permissionsrwx bits for user/group/otherstat.st_mode
Link countNumber of hard linksstat.st_nlink
Owner/GroupUID and GIDstat.st_uid/gid
File sizeBytes (regular files/symlinks)stat.st_size
Timestampsatime, mtime, ctimestat.st_*time
AspectHard LinkSymbolic Link
Points toSame inodePathname string
Cross filesystemNoYes
Link to directoryNo (prevents loops)Yes
Target deletedData remains (link count > 0)Dangling link
Storage overheadNoneStores target path
Terminal window
# Hard link: both names share same inode
ln file hardlink
stat file hardlink # Same inode number
# Symbolic link: stores path to target
ln -s file symlink
readlink symlink # Returns "file"
# Find all hard links to a file
find / -inum $(stat -c %i file) 2>/dev/null
# Find broken symlinks
find /path -xtype l
# Resolve symlink chain
readlink -f symlink # Final target
namei -l symlink # Full chain with permissions
TypeModeDescription
Regular-Ordinary file
DirectorydContains entries
SymlinklPoints to path
BlockbBlock device
CharactercCharacter device
FIFOpNamed pipe
SocketsUnix domain socket

Integer handles for open files, pipes, sockets, devices.

FDNameDefaultShell
0stdinTerminal input< file
1stdoutTerminal output> file
2stderrTerminal error2> file
Process FD Table → Open File Table → Inode Table
[0] ──────────→ [offset, flags] ──→ [file metadata]
[1] ──────────→ [offset, flags] ──→ [file metadata]
[2] ──────────→ [offset, flags] ──→ [file metadata]
Terminal window
# List FDs for a process
ls -la /proc/PID/fd/
# Using lsof
lsof -p PID
# Count open FDs
ls /proc/PID/fd | wc -l
# Check FD limits
ulimit -n # Soft limit
cat /proc/sys/fs/file-max # System-wide limit

Three sets control access for user (owner), group, and other (everyone else):

PermissionFilesDirectories
r (4)Read contentsList contents
w (2)Modify contentsCreate/delete/rename files
x (1)Execute fileAccess directory (cd into it)
OctalPermissionsCommon use
755rwxr-xr-xDirectories, executables
644rw-r—r—Regular files
600rw-------Private files (credentials)
700rwx------Private directories
BitOctalOn FilesOn Directories
setuid4xxxExecute as file ownerNo effect
setgid2xxxExecute as group ownerNew files inherit directory group
sticky1xxxNo modern effectOnly owner can delete files
Terminal window
# Find setuid/setgid files
find / -perm /6000 -type f 2>/dev/null
# Remove setuid bit
chmod u-s /path/to/binary
# Set sticky bit on shared directory
chmod +t /shared

When basic permissions aren’t enough:

Terminal window
# View ACLs
getfacl file.txt
# Set ACL for specific user
setfacl -m u:alice:rw file.txt
# Set ACL for specific group
setfacl -m g:developers:rx directory/
# Default ACL (inherited by new files)
setfacl -d -m g:developers:rwx directory/
# Remove all ACLs
setfacl -b file.txt

Masks permission bits when creating new files:

umaskFiles (from 666)Dirs (from 777)
022644 (rw-r—r—)755 (rwxr-xr-x)
027640 (rw-r-----)750 (rwxr-x---)
077600 (rw-------)700 (rwx------)
Terminal window
umask # View current
umask 027 # Set restrictive default
Terminal window
# Set exact permissions
chmod 750 file
# Add execute for owner
chmod u+x file
# Remove write for group/other
chmod go-w file
# Recursive: read all, execute dirs only
chmod -R a+rX dir/
# Change ownership
chown user:group file
chown -R user dir/
# Show permissions along path
namei -l /path/to/file
# Show octal permissions
stat -c '%a %U:%G %n' *
Terminal window
# Find world-writable files
find / -perm -002 -type f 2>/dev/null
# Find world-writable directories without sticky bit
find / -perm -002 -type d ! -perm -1000 2>/dev/null
Terminal window
# BAD: Predictable, race condition
tmpfile="/tmp/myapp.$$"
echo "data" > "$tmpfile"
# GOOD: Atomic creation with random suffix
tmpfile=$(mktemp /tmp/myapp.XXXXXX)
echo "data" > "$tmpfile"
# BAD
import tempfile
name = tempfile.mktemp() # Race condition
f = open(name, 'w')
# GOOD
fd, name = tempfile.mkstemp() # Atomic
os.write(fd, b'data')

Attacker creates symlink pointing to sensitive file in predictable location.

Mitigations:

  • Use O_NOFOLLOW flag with open()
  • Create temp files in protected directories
  • Enable kernel protections: sysctl fs.protected_symlinks=1
Terminal window
# Find setuid root files
find / -user root -perm -4000 2>/dev/null
# Find world-readable credentials
find /etc -name "*.conf" -perm -004 2>/dev/null | xargs grep -l password
# Check path permissions
namei -l /path/to/sensitive/file