/proc provides direct access to much of the state maintained by the Linux kernel about processes, memory, networking, namespaces, and security parameters. For system administrators, it can be particularly useful when they need to quickly audit a server, investigate an unusual process, or verify system hardening without relying exclusively on higher-level tools. In addition to the usual 18 checks, two particularly useful ones for modern systems are worth adding: NoNewPrivs and Seccomp.
The key /proc security checks in 20 seconds
/procexposes real-time information maintained by the kernel about processes and system configuration.- It can be used to inspect ASLR, capabilities, namespaces,
ptrace, Seccomp, and kernel protections. - It also helps detect deleted executables, RWX memory, unexpected listeners, and suspicious environment variables.
- An unusual result is an indicator to investigate, not automatic proof of compromise.
There is an important point to make before starting. Tools such as ps, ss, sysctl, lsns, lsof, getpcaps, or an EDR are usually more convenient for everyday administration. Many of them obtain at least part of their information from /proc or other kernel interfaces.
Querying /proc directly serves a different purpose: it helps administrators understand what Linux itself is reporting and provides a way to cross-check the output of standard tools.
Processes and memory: seven quick checks
1. Check that ASLR is enabled
Address Space Layout Randomization (ASLR) makes certain memory-corruption attacks more difficult by randomizing the locations used by executables, libraries, the stack, heap, and other memory regions.
cat /proc/sys/kernel/randomize_va_space
Possible values are:
0 ASLR disabled
1 Partial randomization
2 Full randomization
On a conventional production server, a value of 0 should prompt an investigation into why ASLR has been disabled.
The value can also be queried using:
sysctl kernel.randomize_va_spaceCode language: CSS (css)
Changing a parameter directly under /proc/sys affects the running system but will not necessarily survive a reboot. Persistent settings are normally managed through /etc/sysctl.conf or files under /etc/sysctl.d/.
2. Find processes running as root
Linux exposes the real, effective, saved, and filesystem UIDs of every process through /proc/<PID>/status.
grep -H "^Uid:" /proc/[0-9]*/status 2>/dev/null |
grep -E "Uid:[[:space:]]+0[[:space:]]"Code language: JavaScript (javascript)
Having processes with UID 0 is completely normal. systemd and many system services legitimately require elevated privileges.
What matters is finding processes that should not be running as root.
To quickly identify one of the PIDs:
ps -fp <PID>Code language: HTML, XML (xml)
Administrators should also correlate the process with its systemd unit, installed package, executable, and process tree.
3. Find deleted executables that are still running
This is an especially useful check during an investigation:
find /proc/[0-9]*/exe -lname '* (deleted)' -ls 2>/dev/nullCode language: JavaScript (javascript)
Linux can keep a process running after its executable has been removed from the filesystem.
This legitimately happens after some software updates. A daemon may still be executing the previous version of a binary until the service is restarted.
But something like:
/proc/4281/exe -> /tmp/.update (deleted)Code language: JavaScript (javascript)
deserves considerably more attention.
It can be investigated with:
ps -fp 4281
readlink /proc/4281/exe
ls -l /proc/4281/fd
A deleted file does not mean malware. An unexpected deleted executable is an indicator that requires context.
4. Review a process’s capabilities
Linux capabilities divide traditional root privileges into more specific permissions.
grep '^Cap' /proc/<PID>/statusCode language: JavaScript (javascript)
The output includes:
CapInh
CapPrm
CapEff
CapBnd
CapAmb
The hexadecimal masks can be decoded using:
capsh --decode=<value>Code language: HTML, XML (xml)
Another useful tool is:
getpcaps <PID>Code language: HTML, XML (xml)
Particularly sensitive capabilities include:
CAP_SYS_ADMIN
CAP_SYS_PTRACE
CAP_SYS_MODULE
CAP_SYS_RAWIO
CAP_NET_ADMIN
CAP_DAC_OVERRIDE
CAP_SYS_ADMIN deserves particular attention because of the broad range of privileged operations associated with it.
The purpose of an audit should not simply be to find capabilities. It should answer a more useful question: does this service really need these privileges to operate?
5. Look for RWX memory regions
Memory regions that are simultaneously writable and executable can be found with:
grep -E '^[0-9a-f]+-[0-9a-f]+ rwx' /proc/<PID>/mapsCode language: JavaScript (javascript)
A W^X policy attempts to prevent the same memory region from being writable and executable at the same time.
Finding RWX memory does not prove exploitation. Virtual machines, JIT engines, and some specialized applications may legitimately create such mappings.
However, an RWX region in a process that should not generate code dynamically deserves further investigation.
6. Check whether a process is being traced
/proc/<PID>/status also indicates whether another process is tracing it:
grep '^TracerPid:' /proc/<PID>/statusCode language: JavaScript (javascript)
The normal result is:
TracerPid: 0
A non-zero value identifies the tracing process.
It can be investigated using:
ps -fp <TracerPID>
readlink /proc/<TracerPID>/exeCode language: HTML, XML (xml)
strace, gdb, debuggers, observability tools, and some security agents can legitimately explain the result.
If nobody is supposed to be debugging or tracing the process, administrators should determine what is doing it.
7. Compare comm, cmdline, and exe
A Linux process has several identities visible through /proc:
cat /proc/<PID>/comm
tr '\0' ' ' < /proc/<PID>/cmdline
echo
readlink /proc/<PID>/exeCode language: PHP (php)
An unusual example might look like:
comm: kworker
cmdline: /tmp/.cache/python /tmp/.cache/update.py
exe: /usr/bin/python3.13Code language: HTTP (http)
It would be a mistake to automatically classify every mismatch as malicious. Interpreters, scripts, wrappers, application-controlled process names, and the length limit of comm can all create legitimate differences.
The check is useful for finding processes that require an explanation, rather than automatically classifying them as malware.
Privileges, isolation, and containers
8. Review ptrace_scope
The Yama Linux Security Module can restrict which processes are allowed to use ptrace:
cat /proc/sys/kernel/yama/ptrace_scope
Its four levels are:
0 Classic ptrace permissions
1 Restricted ptrace
2 CAP_SYS_PTRACE required
3 ptrace disabled
Level 1 restricts PTRACE_ATTACH according to Yama’s policy in addition to the normal access checks. Level 2 requires CAP_SYS_PTRACE.
Level 3 is particularly restrictive: once configured, it cannot be changed again until the system is rebooted.
For this reason, administrators should not blindly change this parameter on production systems. Doing so can break debugging, diagnostics, and some monitoring agents.
9. Review the PID namespace
To determine which PID namespace a process belongs to:
readlink /proc/<PID>/ns/pidCode language: HTML, XML (xml)
For example:
pid:[4026532921]Code language: CSS (css)
It can be compared with PID 1:
readlink /proc/1/ns/pid
readlink /proc/<PID>/ns/pidCode language: HTML, XML (xml)
Different identifiers mean that the processes belong to different PID namespaces.
On Docker, Podman, Kubernetes, or LXC hosts, this can help verify the expected process isolation.
10. Inspect root and cgroup
Two additional checks help determine the environment in which a process is running:
readlink /proc/<PID>/root
cat /proc/<PID>/cgroupCode language: HTML, XML (xml)
On containerized systems, this information can help correlate a host PID with its container.
There is an important caveat: finding / in certain contexts does not prove a container escape.
Namespaces, runtime configuration, mounts, and cgroups need to be analyzed together.
11. Check NoNewPrivs
This is one of the two checks worth adding to the original list.
grep '^NoNewPrivs:' /proc/<PID>/statusCode language: JavaScript (javascript)
When no_new_privs is set, execve() cannot grant the process new privileges through mechanisms such as set-user-ID/set-group-ID bits or file capabilities.
It is particularly useful when auditing services and containers that are expected to run under restrictive policies.
In systemd, it can be associated with configurations such as:
NoNewPrivileges=yes
Not every process needs to have it enabled. Its absence is not automatically a vulnerability.
12. Check Seccomp
The second addition is especially useful for containers and modern services:
grep -E '^(Seccomp|Seccomp_filters):' /proc/<PID>/statusCode language: JavaScript (javascript)
The Seccomp values are:
0 SECCOMP_MODE_DISABLED
1 SECCOMP_MODE_STRICT
2 SECCOMP_MODE_FILTER
The kernel may also expose Seccomp_filters, showing the number of filters attached to the process.
Seccomp can restrict which system calls a process is allowed to make.
On container hosts, it is particularly useful to compare processes with:
grep -E '^(Name|Pid|NoNewPrivs|Seccomp|Seccomp_filters):' /proc/<PID>/statusCode language: JavaScript (javascript)
This provides a quick way to verify whether a process that is supposed to be confined actually has Seccomp filters enabled.
Networking, kernel, and hardening: eight more checks
13. Review suspicious environment variables
A process’s environment is available through:
tr '\0' '\n' < /proc/<PID>/environCode language: JavaScript (javascript)
For a quick security-focused review:
tr '\0' '\n' < /proc/<PID>/environ |
grep -E '^(LD_PRELOAD|LD_LIBRARY_PATH|HTTP_PROXY|HTTPS_PROXY|ALL_PROXY|NO_PROXY)='Code language: JavaScript (javascript)
An unexpected LD_PRELOAD deserves attention because it can cause additional libraries to be loaded into a process.
Unknown proxy settings are also worth investigating because they may alter where network traffic is sent.
Access permissions matter here. Access to some /proc/<PID> files is subject to kernel security checks, so ordinary users cannot necessarily inspect the environment of arbitrary processes.
14. Find listeners directly through /proc/net/tcp
IPv4 TCP sockets can be inspected with:
cat /proc/net/tcp
To display sockets in the LISTEN state:
awk '$4 == "0A"' /proc/net/tcpCode language: JavaScript (javascript)
Ports are represented in hexadecimal.
For example:
0016
corresponds to decimal port 22.
For daily system administration, this is much easier:
ss -lntp
But /proc/net/tcp is useful for understanding the underlying kernel information and during low-level investigations.
For IPv6 there is also:
/proc/net/tcp6
15. Review kernel boot parameters
cat /proc/cmdline
Administrators should look for parameters related to the security policies of their distribution and server, such as:
lockdown=
selinux=
apparmor=
mitigations=
pti=
vsyscall=
Unexpected changes that disable mitigations expected to be active deserve particular attention.
There is no universally correct kernel command line. The appropriate configuration depends on the kernel, distribution, architecture, workload, and hardening policy.
16. Review loaded kernel modules
cat /proc/modules
A more readable alternative is:
lsmod
During an investigation, administrators should look for unknown or unexpected modules and verify where they came from.
For example:
modinfo <module>Code language: HTML, XML (xml)
Kernel modules execute with extremely high privileges. A module that cannot be associated with the server’s hardware, software, or expected configuration therefore requires investigation.
17. Check kptr_restrict
cat /proc/sys/kernel/kptr_restrict
This parameter restricts the exposure of kernel pointer addresses through interfaces such as /proc/kallsyms.
A value of 2 applies the strongest restriction among the available settings.
It can also be queried with:
sysctl kernel.kptr_restrictCode language: CSS (css)
Before changing it, administrators should consider the requirements of debugging, observability, and other tools running on the server.
18. Restrict access to dmesg
cat /proc/sys/kernel/dmesg_restrict
With:
1
access to the kernel log is restricted according to the corresponding privilege checks.
dmesg can reveal useful information to an attacker, including hardware details, driver information, errors, and, depending on the configuration and kernel version, other internal kernel data.
19. Check hardlink protection
cat /proc/sys/fs/protected_hardlinks
When set to 1, Linux restricts the creation of hardlinks to files that the user does not own except under specific conditions.
This protection is designed to reduce a historical class of attacks involving race conditions and hardlinks, particularly in shared directories.
20. Review symlink protection and complete /tmp hardening
The original set of checks ends with:
cat /proc/sys/fs/protected_symlinks
A value of 1 enables restrictions intended to reduce attacks involving symbolic links inside sticky, world-writable directories.
A modern sysadmin should take the opportunity to check these four parameters together:
sysctl fs.protected_symlinks
sysctl fs.protected_hardlinks
sysctl fs.protected_fifos
sysctl fs.protected_regularCode language: CSS (css)
The last two are particularly useful and are often missing from older hardening checklists.
protected_fifos helps prevent accidental writes to a FIFO controlled by another user when an application expected to create a regular file.
protected_regular applies a similar concept to regular files in sticky, world-writable directories.
On systems that support them, all four are worth reviewing together.
A quick /proc security check worth keeping handy
Several non-destructive checks can be grouped together to obtain a quick snapshot of a server:
echo '=== ASLR ==='
cat /proc/sys/kernel/randomize_va_space
echo '=== Yama ptrace ==='
cat /proc/sys/kernel/yama/ptrace_scope 2>/dev/null || echo "Yama unavailable"
echo '=== Kernel pointers ==='
cat /proc/sys/kernel/kptr_restrict
echo '=== dmesg ==='
cat /proc/sys/kernel/dmesg_restrict
echo '=== Hardlinks ==='
cat /proc/sys/fs/protected_hardlinks
echo '=== Symlinks ==='
cat /proc/sys/fs/protected_symlinks
echo '=== FIFOs ==='
cat /proc/sys/fs/protected_fifos 2>/dev/null
echo '=== Regular files ==='
cat /proc/sys/fs/protected_regular 2>/dev/null
echo '=== Deleted executables ==='
find /proc/[0-9]*/exe -lname '* (deleted)' -ls 2>/dev/nullCode language: PHP (php)
The output should not be turned into a simplistic pass-or-fail test.
Real hardening depends on the distribution, kernel, server role, applications, containers, and threat model. Even sensible security controls can interfere with legitimate tools.
There is another useful check for multi-user servers: inspect how /proc itself is mounted.
findmnt -no TARGET,FSTYPE,OPTIONS /proc
Linux supports the hidepid mount option, which can restrict how much information users can see about processes belonging to other users.
This is not included as one of the 20 checks because it is not strictly a query against a /proc file, but it deserves a place in any serious review of a shared Linux server.
The best way to use these checks is not to run them once and forget the results. The real value comes from understanding the server’s normal state and identifying deviations from that baseline.
A process with a powerful capability can be legitimate. A deleted binary may be the result of an update. A new listener might belong to a recently deployed service.
The situation becomes more interesting when several signals appear together: an unknown process running as root, a deleted executable under /tmp, an unexpected LD_PRELOAD, elevated capabilities, and a listening socket on a port that does not appear in the expected inventory.
At that point, /proc stops being merely an interesting kernel interface and becomes a very practical starting point for an incident investigation.
Frequently asked questions
What is /proc in Linux?
/proc is a virtual filesystem through which the Linux kernel exposes information about processes and various system parameters. The /proc/<PID> directories provide information specific to each running process.
Which /proc checks are most useful during a security incident?
Deleted executables, cmdline, exe, capabilities, TracerPid, memory maps, environment variables, namespaces, and sockets can quickly provide context about a suspicious process. The findings should be correlated with logs, systemd, installed packages, network connections, and security tools.
How can I tell whether a Linux process is using Seccomp?
Run grep -E '^(Seccomp|Seccomp_filters):' /proc/<PID>/status. A Seccomp: 2 result indicates that the process is running in Seccomp filter mode.
Is checking /proc enough to audit Linux security?
No. /proc provides an excellent view of the kernel’s current state, but a complete audit should also cover permissions, users, systemd services, packages, logs, firewall rules, SSH, mandatory access control systems such as SELinux or AppArmor, integrity controls, updates, and network configuration.
Sources:
- Linux Kernel Documentation, official
/proc/sys/fs/documentation. - Linux Kernel Documentation, Yama Linux Security Module and
ptrace_scope. - Linux man-pages,
proc(5),proc_pid(5),proc_pid_status(5), andcapabilities(7). - Original material covering 18 security checks using
/proc.
