Virtual Filesystems: /proc, /sys and tmpfs
- Recognise proc, sysfs, tmpfs and devtmpfs mounts and what each holds
- Read live kernel and process information from /proc and /sys
- Mount a tmpfs with a size cap, owner and mode, and make it persistent in fstab
- Hide other users' processes with the hidepid option, now and at boot
Filesystems with no disk behind them
Recognise the virtual filesystems on a running system and what each one is for.
Most filesystems store data on a disk. A virtual filesystem stores nothing on disk at all. The kernel makes its contents up on the fly, or keeps them in memory, and presents them through the same open, read and write calls as ordinary files. That's the Unix idea of "everything is a file" carried to its conclusion: process tables, kernel settings and device lists all become files you can read with
cat.You'll meet four constantly:
- proc at
/proc: one directory per running process, plus kernel state and tunables under/proc/sys. - sysfs at
/sys: the kernel's model of devices, drivers and buses. - tmpfs: a filesystem that lives in RAM (and swap).
/dev/shmand often/runare tmpfs, and you can mount your own. - devtmpfs at
/dev: device nodes the kernel creates for hardware it finds.
findmnt -t proc,sysfs,tmpfs,devtmpfs -o TARGET,FSTYPE,OPTIONS | head -8TARGET FSTYPE OPTIONS /proc proc rw,nosuid,nodev,noexec,relatime /dev tmpfs rw,nosuid,size=65536k,mode=755 └─/dev/shm tmpfs rw,nosuid,nodev,noexec,relatime,size=65536k /sys sysfs rw,nosuid,nodev,noexec,relatime └─/sys/fs/cgroup tmpfs rw,nosuid,nodev,noexec,relatime,mode=755
- -t TYPES
- Show only mounts of these filesystem types.
- -o COLS
- Choose the output columns.
findmnt filters by type with -t. Every row here is a mount that occupies no disk space. The OPTIONS column matters: tmpfs mounts show theirsize=cap, and /proc shows its hardening options, which you'll change later.Check yourself
Does writing a 50 MB file to a tmpfs mount use disk space?
- proc at
Reading the kernel through /proc and /sys
Pull live information from /proc and /sys with ordinary file tools.
Because these are files, the tools you already know are the interface.
catreads a value andechointo a writable file changes a setting at once. Changes made this way last until reboot, which is why permanent kernel settings go throughsysctl.dfiles, a topic of its own. Here the goal is to get comfortable reading.grep -E '^(MemTotal|MemAvailable|SwapTotal):' /proc/meminfoMemTotal: 16480968 kB MemAvailable: 15644964 kB SwapTotal: 0 kB
/proc/meminfo is where freegets its numbers. MemAvailable is the honest answer to "how much memory can a new program get", because it counts cache that the kernel can reclaim.grep -E '^(Name|State|PPid|VmRSS):' /proc/self/statusName: grep State: R (running) PPid: 22 VmRSS: 2248 kB
Every process has a directory named after its PID, and /proc/selfalways points at the process doing the reading, here grep itself. status shows its name, state, parent PID and resident memory. This is the raw data ps and top format for you.ls /sys/class/net && cat /sys/class/net/lo/mtueth0 lo 65536
sysfs groups devices by class. Each network interface has a directory full of one-value files. lo's MTU is 65536. Writing a new value into such a file changes it live, the same way ip link setwould.A useful way to keep the two apart: /proc is about processes and the running kernel, and /sys is about devices. When you need to know what a program is doing, its open files (
/proc/PID/fd), its limits (/proc/PID/limits) or its environment, you look in /proc. When you need to know what hardware the kernel found, which driver claimed it, or a device setting such as an interface MTU or a disk's scheduler, you look in /sys. Many command-line tools are thin readers of these two trees.Check yourself
Which file shows the status of the process that reads it, whatever its PID?
Mounting a tmpfs with a size, an owner and a mode
Create a RAM-backed scratch area with the right limits and ownership, now and at boot.
An unlimited tmpfs can grow until it eats half of RAM, its default cap, so you always give it a size. Its root directory is created fresh at every mount, so ownership and permissions have to be set as mount options (
uid=,gid=,mode=). Achownafter mounting works until the next reboot and then silently disappears.id app >/dev/null 2>&1 || useradd -m -s /bin/bash app; mkdir -p /srv/scratch && mount -t tmpfs -o size=64M,uid=app,gid=app,mode=0750 tmpfs /srv/scratch && findmnt /srv/scratch && stat -c '%U %G %a' /srv/scratchTARGET SOURCE FSTYPE OPTIONS /srv/scratch tmpfs tmpfs rw,relatime,size=65536k,mode=750,uid=1001,gid=1001 app app 750
- -t tmpfs
- The filesystem type.
- size=64M
- Cap the filesystem at 64 MiB.
- uid=/gid=
- Owner and group of the root directory.
- mode=0750
- Permissions of the root directory.
This mounts a 64 MiB tmpfs owned by app with mode 750. findmnt reports the size as 65536k, the kernel's own unit, and stat confirms the owner and mode came from the options. umount /srv/scratch && echo 'tmpfs /srv/scratch tmpfs size=64M,uid=app,gid=app,mode=0750 0 0' >> /etc/fstab && mount /srv/scratch && findmnt --fstab /srv/scratchTARGET SOURCE FSTYPE OPTIONS /srv/scratch tmpfs tmpfs size=64M,uid=app,gid=app,mode=0750
- --fstab
- Show the entry from /etc/fstab instead of the live mount.
To make it permanent, add an fstab line and mount from it. If mount /srv/scratchworks with no other arguments, the line is valid, and you've proved it before a reboot depends on it. For tmpfs the first field is only a label.tmpfsornoneare conventional.Check yourself
You mounted a tmpfs and then ran
chown app /srv/scratch. Who owns /srv/scratch after a reboot?Hiding other users' processes with hidepid
Remount /proc so ordinary users only see their own processes, and keep it that way.
By default any user can list every process on the box and read its command line, which can include passwords passed as arguments, internal hostnames and file paths. procfs has a mount option, hidepid, that fixes this: with
hidepid=invisible(older spelling:hidepid=2) an unprivileged user can only see their own process directories. root still sees everything.id intern >/dev/null 2>&1 || useradd -m -s /bin/bash intern; runuser -u intern -- ls /proc | grep -c '^[0-9]'5
Before the change: intern counts every PID directory on the system, including root's. The number depends on what's running, but it's more than intern's own handful. mount -o remount,hidepid=invisible /proc && findmnt -n -o OPTIONS /proc && runuser -u intern -- ls /proc | grep -c '^[0-9]'rw,nosuid,nodev,noexec,relatime,hidepid=invisible 1
- -o remount,OPTS
- Change the options of an already-mounted filesystem.
remount changes the options of the mounted /proc in place. The count drops to intern's own processes, here just the lsitself. For persistence, addproc /proc proc defaults,hidepid=invisible 0 0to /etc/fstab, thenmount -o remount /procre-reads it.mount -o remount,hidepid=0 /proc && findmnt -n -o OPTIONS /procrw,nosuid,nodev,noexec,relatime
- hidepid=0
- Show all processes to everyone again (the default).
This puts the lesson box back the way it was, so the practice step starts from the default. On a real server you'd leave hidepid on. Check yourself
Which /proc mount option lets members of the group monitor see all processes while hidepid=invisible is on?
Now do it — in your live terminal
Configure a tmpfs and harden /proc yourself on the sandbox to your right.
Put it together on the sandbox. For each step, write down what findmnt or stat should print before you press Enter, then compare. Keep the habit of writing the fstab line first and mounting from it. That's how you know a reboot won't surprise you, and it's exactly what the lab grades: the live mount and the fstab entry, which have to agree with each other.
mkdir -p /mnt/fast && echo 'tmpfs /mnt/fast tmpfs size=32M,mode=1777 0 0' >> /etc/fstab && mount /mnt/fast && df -h /mnt/fastdf should show a 32M filesystem of type tmpfs. echo 'proc /proc proc defaults,hidepid=invisible 0 0' >> /etc/fstab && mount -o remount /proc && findmnt -n -o OPTIONS /procThe options should now include hidepid=invisible, read from fstab. useradd -m peek; runuser -u peek -- ps -e | wc -lA brand-new user should see only a couple of lines: their own processes.
- Virtual filesystems have no disk behind them: proc and sysfs are generated by the kernel, and tmpfs lives in RAM.
- /proc holds a directory per process plus kernel state and tunables; /sys models devices. Read them with cat and grep.
- Always give a tmpfs a size=, and set ownership with uid=, gid= and mode= mount options, because the root directory is recreated at every mount.
- hidepid=invisible on /proc limits ordinary users to their own processes; gid= exempts a monitoring group.
- Write the fstab line first, then mount from it, so the live state and the boot state can't disagree.
| Command / option | What it does |
|---|---|
findmnt -t proc,sysfs,tmpfs | List virtual filesystem mounts and their options |
/proc/PID/status, /proc/meminfo | Process details and memory figures |
/sys/class/net/IFACE/ | One-value files describing a network interface |
mount -t tmpfs -o size=64M,uid=U,mode=0750 tmpfs DIR | RAM-backed mount with a cap, owner and mode |
mount -o remount,hidepid=invisible /proc | Hide other users' processes now |
findmnt --fstab DIR | Check what fstab will mount at boot |
