Skip to main content

Command Palette

Search for a command to run...

The Linux File System

Published
9 min read
The Linux File System

In this article, we are going to learn about the Linux File System, this article is no going to be another list of linux commands, but this will help you to know some rarely used and less known but important features of Linux file system.

Before diving into the advance features, It is a good idea to know about the basic commands of Linux file system.

Filesystem Commands ( Frequently used )

There are several commands in linux to perform different tasks. Here is the list of few commands, based on their use cases :

pwd          # Current directory
ls           # List files
cd <dir>     # Move between directories
tree         # Visualize folder structure

File Operations

touch file.txt    # touch command for file creation
mkdir folder      # mkdir for creating directory 
cp file1 file2    # cp command for copying data from one file to another
mv old new        # mv command to move data from old file to new one
rm file           # rm command to delete the file

Reading System Files

cat <file>
less <file>
head <file>
tail -f <file>

Searching & Investigation

find / -name "file"
grep "text" file
locate filename

There are a lot more commands available in Linux, other then above commands.

Let's discuss about the findings during the research of linux commands

The linux file system, is not just storage mechanism or filesystem, but it is a live interface to the Kernel itself.

Finding 1 : The Routing Table is Just a File

Path : /proc/net/route

The kernel maintains a live routing table, the logic that decides where every outgoing packet goes and exposes it as a plain text file at /proc/net/route. No tool required. No daemon to query. Just a file.

Each row is a route. The columns are hex-encoded: destination, gateway, flags, interface. The system reads this to decide whether a packet should go to the local network or out through the default gateway.

cat /proc/net/route
# Iface  Destination  Gateway   Flags  ...  Mask
# eth0   00000000     0101A8C0  0003        00000000  ← default route → 192.168.1.1
# eth0   0001A8C0     00000000  0001        00FFFFFF  ← local subnet

/proc is not a real disk; it's a virtual filesystem the kernel generates on-the-fly. Reading /proc/net/route is essentially reading a live kernel data structure without any syscall overhead beyond a plain file read.

Finding 2 : DNS Is Not the First Stop

Path: /etc/nsswitch.conf

Many people assume that when you type a hostname, Linux immediately fires a DNS query. But it doesn't. The actual resolution order is controlled by /etc/nsswitch.conf, the Name Service Switch configuration. One line controls everything :


hosts: files dns mdns4_minimal

This means: check /etc/hosts first, then DNS, then mDNS. Before a single DNS packet leaves your machine, the kernel checks the local hosts file. This is why sysadmins can override any domain locally add an entry to /etc/hosts and it wins over DNS every time, unless nsswitch is reconfigured.

Security implication: Malware sometimes modifies /etc/hosts to redirect banking domains to phishing IPs. Since files comes before dns in the default config, this works silently, without touching any DNS server, without any network anomaly to detect.

Finding 3 : Every Process Keeps Its Open Files

Path: /proc/[pid]/fd/

Every running process has a directory at /proc/[pid]/fd/ containing symbolic links, one for each open file descriptor. This includes open log files, sockets, pipes, devices, and config files.

ls -la /proc/$(pgrep nginx)/fd
# 0 → /dev/null
# 1 → /dev/null
# 4 → socket:[38291]
# 5 → /var/log/nginx/access.log

What's remarkable : if a process opens a file and that file is then deleted from disk, the process still holds the file descriptor open. The file's data survives on disk, invisible from the directory tree, but still readable via /proc/[pid]/fd/[n].

The ghost file phenomenon: This is a known disk space recovery trick. If df shows a disk is full but du shows low usage, a deleted-but-still-open log file is silently holding the space. You can truncate it via its fd path and reclaim the space without killing the process. The file is gone from the directory, but alive in /proc.

Finding 4 : Privilege Is Just a Text File

Path: /etc/sudoers

The entire privilege escalation model of Linux rests on a single text file. /etc/sudoers defines exactly who can run what as whom. Its syntax is precise and unforgiving, a mistake here can lock out all admin access permanently.

root    ALL=(ALL:ALL) ALL
%sudo   ALL=(ALL:ALL) ALL

# This line lets the "deploy" user restart nginx without a password:
deploy  ALL=(root) NOPASSWD: /bin/systemctl restart nginx

The NOPASSWD directive is powerful for automation, but catastrophic if misconfigured. A wildcard like NOPASSWD: ALL on a service account is functionally equivalent to giving that account root access without any authentication.

Finding 5 : One File Turns Linux Box Into a Router

Path: /proc/sys/net/ipv4/ip_forward

There is a single file that controls whether Linux will forward network packets between interfaces, the defining behavior of a router. It contains either 0 or 1.

cat /proc/sys/net/ipv4/ip_forward
0   # not routing

echo 1 > /proc/sys/net/ipv4/ip_forward
# Now this machine forwards packets between interfaces.
# Combined with iptables NAT rules → full router or VPN gateway.

VPNs, Docker networking, Kubernetes pod routing, and NAT gateways all depend on this being set to 1. Every container platform enables this silently at startup, through a single write to a single file.

Finding 6 : How the OS Finds Shared Libraries

Path: /etc/ld.so.conf and /etc/ld.so.cache

When a program launches, the dynamic linker needs to find .so shared library files. The directories it searches are listed in /etc/ld.so.conf and files inside /etc/ld.so.conf.d/.

These are compiled into a fast binary cache at /etc/ld.so.cache by running ldconfig.

cat /etc/ld.so.conf.d/x86_64-linux-gnu.conf
/lib/x86_64-linux-gnu
/usr/lib/x86_64-linux-gnu

The LD_PRELOAD hijacking attack: The LD_PRELOAD environment variable forces a library to load before anything else, overriding the standard library search entirely. Attackers use this to intercept system calls at the libc level. Classic rootkits used LD_PRELOAD to hide processes from ps by overriding the very libc functions used to enumerate them. The process was running; ps just never saw it.

Finding 7 : The Auth Log Knows Everything

Path: /var/log/auth.log

The auth log knows everything about who came in.

Every authentication event, successful login, failed login, sudo usage, SSH key acceptance, is written to /var/log/auth.log (on Debian/Ubuntu; /var/log/secure on RHEL/CentOS). It is the system's silent witness.

Apr 22 03:14:22 sshd[2891]: Failed password for root from 45.33.32.156 port 43212 ssh2
Apr 22 03:14:23 sshd[2891]: Failed password for root from 45.33.32.156 port 43212 ssh2
Apr 22 09:01:11 sudo:  alice : TTY=pts/1 ; USER=root ; COMMAND=/bin/cat /etc/shadow

That last line is alarming: alice used sudo to read /etc/shadow the file containing all password hashes. Auth logs are the first place to check after any suspected breach.

Finding 8 : Scheduled Tasks Are Scattered Across the Filesystem

Paths: /etc/cron.d/ · /etc/cron.daily/ · /var/spool/cron/crontabs/

Most people know about crontab -e. What they don't realize is that cron jobs live in at least four different locations. Package managers drop cron jobs in /etc/cron.d/. The system runs daily/weekly/monthly scripts from /etc/cron.daily/, /etc/cron.weekly/, and so on. User-specific crontabs live in /var/spool/cron/crontabs/[username].

ls /etc/cron.d/
# certbot   e2scrub_all   php   sysstat

cat /etc/cron.d/certbot
# 0 */12 * * * root certbot renew -q

Certbot silently auto-renews your TLS certificates every 12 hours, a cron job you probably never set up yourself, living in a directory you may never check.

Finding 9 : Devices That Aren't Physical

Path: /dev/null, /dev/zero, /dev/random

The /dev directory contains device files, but not all of them represent hardware. Three of the most useful are entirely virtual, implemented purely in kernel code.

/dev/null is the black hole. Anything written to it is discarded. Reading from it returns EOF immediately. It exists to silence output you don't care about.

/dev/zero produces an infinite stream of zero bytes. It's used to create empty files of exact sizes, dd if=/dev/zero of=disk.img bs=1M count=100 creates a precise 100MB blank file, useful for disk image creation and benchmarking.

/dev/random and /dev/urandom are sources of cryptographically random bytes, fed by entropy gathered from hardware events: keystrokes, disk I/O timing, network packet arrival. Every TLS key, SSH key, and cryptographic token generated on Linux is seeded from here.

Finding 10 : Reading Live TCP Connections Without Any Tool

Path: /proc/net/tcp

Here is something that genuinely surprised me: netstat and ss have no special kernel access. They are just reading /proc/net/tcp , a file that lists every active TCP socket in the kernel right now, in plain text. The tools just decode it for you.

cat /proc/net/tcp
#  sl  local_address  rem_address  st  ...  inode
   0:  00000000:0016  00000000:0000  0A  ...  12938   ← LISTEN on port 22 (SSH)
   1:  0F02000A:0016  0202000A:C4E2  01  ...  18342   ← ESTABLISHED connection

The addresses are little-endian hex. 0016 hex = 22 decimal — that's SSH. State 0A = LISTEN. State 01 = ESTABLISHED. The inode column links the socket back to a specific process via /proc/[pid]/fd/.

Decoding the address manually:

# 0F02000A → bytes reversed: 0A 00 02 0F → 10.0.2.15
printf '%d.%d.%d.%d\n' 0x0A 0x00 0x02 0x0F
# 10.0.2.15

Conclusion

The deeper insight from this investigation is architectural. Linux exposes its own internals as files. Routing tables, process state, socket connections, kernel tunables, all of it is readable, and sometimes writable, through the filesystem. This is not accidental. It is the Unix philosophy made real: everything is a file, and files can be read.

If you understand the filesystem, you understand the system. You don't need a monitoring tool if you can read /proc. You don't need a network scanner if you can parse /proc/net/tcp. The OS is already telling you everything, you just need to know where to look.