Linux System Programming · intermediate · ~20 min
Build defensive tooling that parses `/proc` fields safely and reliably.
If you build defender tooling on Linux, parsing /proc is the foundation. (/proc is a virtual filesystem the kernel exposes; reading its text files lets you inspect running processes.)
unknown rather than 0.Tools like osquery, falco, auditd, and essentially every Linux DFIR (Digital Forensics and Incident Response) tool read /proc.
A bug in one of those parsers becomes a missed detection.
Not all /proc fields are equally dependable across kernel versions:
VmRSS, VmPeak, Threads, Pid, PPid, Uid, Name.Cgroup, NSpgid, SigQ.A PID (process ID) can disappear between the moment you open /proc/PID/ and the moment you read a file inside it.
Always handle ENOENT (the "no such file" error) on every read after the first.
A defender's tool that crashes on a fast-cycling PID is itself a vulnerability: a denial-of-defense.
To prove your tool is robust, test it against a process that churns rapidly, for example:
bash -c 'while true; do true; done'
sscanf with explicit width specifiers.man 5 proc is the canonical reference. It is large but well indexed.
The recipes lesson showed how to use /proc. This lesson is for engineers writing the forensic tools themselves.
When you build those tools:
FILE fp = fopen("/proc/self/status", "r"); / read this process's status file / char line[512]; / fixed, bounded line buffer / long vm_rss_kb = -1; / -1 means "not found / unknown" / while (fgets(line, sizeof line, fp)) / read one line at a time / if (sscanf(line, "VmRSS: %ld kB", &vm_rss_kb) == 1) break; / match field, stop on success */ fclose(fp);
VmRSS line by lineFILE *fp = fopen("/proc/self/status", "r"); /* read this process's status file */
char line[512]; /* fixed, bounded line buffer */
long vm_rss_kb = -1; /* -1 means "not found / unknown" */
while (fgets(line, sizeof line, fp)) /* read one line at a time */
if (sscanf(line, "VmRSS: %ld kB", &vm_rss_kb) == 1) break; /* match field, stop on success */
fclose(fp);
fopen opens the status file for reading.line[512] bounds how much of any single line we accept.vm_rss_kb = -1 is the "unknown" default, not 0.fgets reads one bounded line per iteration.sscanf returns 1 only when the field matched; we then stop./proc fields are stable across kernel versions. They are not always.Diff your tool's output against a known-good baseline:
ps -o pid,rss,vsz,comm
/proc files reject pread. Always read them sequentially with fgets.osquery, falco, auditd, htop, monitorix, and effectively every observability agent.
VmRSS from /proc/self/status.comm and state./proc work = robust parsing + race awareness + capped reads.unknown, never 0, on a parse failure.ENOENT: any PID can vanish mid-read.