Reading Process Information Without Root Using Linux Capabilities
Published: September 17, 2026
Introduction
Linux exposes a running process's executable and mapped libraries through
/proc. This information helps check runtime usage of packages reported
by container vulnerability scans. Reading another user's process
information, however, may require additional permissions.
Linux capabilities let a collector run as a non-root user with selected
privileges. To narrow the privileges granted to the collector, the
validation checked which capability combinations could retrieve the
information collected as root. Using root collection as the baseline,
it compared three non-root conditions: no capabilities, CAP_SYS_PTRACE
alone, and CAP_SYS_PTRACE with CAP_DAC_READ_SEARCH.
The following combinations worked in the measurement environment.1516
| Information collected | Capabilities required for non-root collection in the measurement |
|---|---|
Executables and loaded libraries used to check package usage (exe and maps) |
CAP_SYS_PTRACE |
The above plus information linking listening sockets to processes (fd/) |
CAP_SYS_PTRACE and CAP_DAC_READ_SEARCH |
This article covers the following:
- Linux capabilities relevant to reading process information.
- How ptrace access checks and file permissions interact.
- Measured results for four root and non-root permission conditions.
- The actual measurement collector and how it records its results.
- What to check when access still fails.
What Linux capabilities are
Linux capabilities divide traditional root privileges by operation. They are maintained per thread; permission checks use the effective set.1
Two capabilities are particularly relevant here:
| Capability | Role |
|---|---|
CAP_SYS_PTRACE |
Authorizes ptrace operations and access to protected process information under /proc |
CAP_DAC_READ_SEARCH |
Bypasses ordinary file-read and directory-read/search permission checks |
CAP_SYS_PTRACE also permits operations that modify another process's
memory. CAP_DAC_READ_SEARCH is not limited to /proc.
Grant these capabilities only to programs needed for collection, and
restrict which users can execute those programs.1
Why CAP_SYS_PTRACE is not enough to read everything
In the measurement, granting CAP_SYS_PTRACE to the non-root collector
allowed it to read exe and maps. Listing fd/ still failed with a
permission error. Adding CAP_DAC_READ_SEARCH allowed that operation to
succeed.16
The difference comes from two separate checks: permission to access the target process's information, and permission to access a directory.
Permission to read exe and maps
The exe link identifies the executable, while maps describes memory
mappings, including loaded files. When these entries are read, Linux
checks whether the reader may access the target process's information.
This is the ptrace access check, where CAP_SYS_PTRACE is
relevant.342
In the measurement environment, granting CAP_SYS_PTRACE allowed the
collector to pass this check and identify executables and loaded
libraries.16
Linux manuals call the read check used for exe and maps
PTRACE_MODE_READ_FSCREDS. Despite the name, this checks permission to
read information without attaching a debugger.2
Permission to list fd/
The fd/ directory contains links to a process's open files and sockets.
Inspecting them involves listing the directory first, then reading each
link.5
In the measurement, the target's fd/ was owned by root with mode 0500.
The non-root collector lacked permission to list it. CAP_SYS_PTRACE
did not bypass that restriction, so enumeration failed with EACCES
(permission denied).166
Adding CAP_DAC_READ_SEARCH bypassed the directory-permission restriction
and allowed enumeration. Reading the links afterward also involves a
ptrace access check, as with exe.15
With only CAP_SYS_PTRACE, the collector could therefore confirm package
use through loaded files, but could not use fd/ to attribute listening
sockets to processes.16
Similarly, reading a container file through /proc/<pid>/root requires
both access to process information and permissions on the files and
directories reached through that link.7 Required permissions depend
on the target; procfs mount settings and Linux Security Modules (LSMs),
such as AppArmor and SELinux, also impose restrictions.82
Results for four permission conditions
The September 12, 2026 measurement compared four conditions for a collector
running directly on a Docker host. The main environment was WSL2 Linux
6.6.114 and Docker Engine 29.1.3, with no hidepid restriction. Non-root conditions used file capabilities on the
compiled executable.151617
Yama was set to ptrace_scope=1 during the measurement. This setting does
not directly restrict the exe and maps reads used here.9
| Collector condition | Package-use confirmation | Listener attribution | Main result |
|---|---|---|---|
| Root | Baseline | Available | Baseline collection succeeded |
Non-root with CAP_SYS_PTRACE and CAP_DAC_READ_SEARCH |
Same as root | Same as root | Obtained the information compared in this measurement |
Non-root with CAP_SYS_PTRACE |
Same as root | Unavailable | Listing fd/ was denied |
| Non-root without capabilities | Every sample failed observation | Unknown | Required process information could not be collected |
In this environment, CAP_SYS_PTRACE alone allowed reading exe, maps,
namespace links, and package metadata through root. Permissions inside
a container may require CAP_DAC_READ_SEARCH for metadata access as
well.16
Failure without capabilities does not mean that every procfs entry,
including status, was unreadable. The table describes whether collection
provided the information required to confirm package use.
Non-root capability combinations remain unverified with an AppArmor
profile applied to the collector.
In a later operational-environment validation,
the collector ran unconfined under AppArmor, and a non-root collector with
CAP_SYS_PTRACE and CAP_DAC_READ_SEARCH achieved 12/12 valid reads and
matched root on every compared measure.
These results do not establish a universal minimum permission set for Linux
hosts.15
The program used for the measurement
The four permission conditions were measured with runtime-discovery, a
collector implemented in Go. The published sampling version (ed7813e)
is available in its README and
source code.
What it reads
The collector obtains container host PIDs through the Docker API, then
reads the host's /proc. The main read operations are implemented in the
published version of procfs.go.
| Function | Information read | Relevant permissions |
|---|---|---|
readExe |
The exe link target |
Identifying the executable involves a ptrace read access check |
readMaps |
Executable file mappings in maps |
Identifying loaded files involves a ptrace read access check |
socketInodesForPID |
Entries in fd/ and socket inodes from their links |
Both directory permissions and ptrace checks on the links apply |
readStatus |
The target process's effective UID and CapEff |
Records the privileges of the observed process |
socketInodesForPID first lists fd/, then reads each link. With only
CAP_SYS_PTRACE, the measurement failed at the enumeration step. Package
use could still be confirmed through mappings, but the information needed
to attribute listening sockets to a PID was unavailable.
How permission conditions and failures are recorded
The collector's -permission argument labels the condition in the
results. It does not grant privileges.17
| Label | Measurement condition |
|---|---|
root |
Run as root |
ptrace |
Run as non-root with CAP_SYS_PTRACE on the compiled executable |
ptrace_dac |
Run as non-root with CAP_SYS_PTRACE and CAP_DAC_READ_SEARCH |
none |
Run as non-root without capabilities |
The permission comparison used a compiled executable, rather than
go run. The published README describes the environment,
build, collection, and matching procedures.
Failed operations are retained in the observations. After matching,
permissions.csv reports the operation, result, occurrence count, and
error message, among other fields. The output is implemented in
match_report.go. This allows comparison of which
operations failed under each permission condition and how those failures
affected package-use confirmation.
When access still fails
Check both the file configuration and runtime privileges
getcap reports file capabilities, not the privileges of an already
running process.11 Compare it with CapEff in the reader's
/proc/<pid>/status. The collector's readStatus function records the
observed target's privileges, so check the collector's privileges separately. Running cat /proc/self/status reports information about cat;
use the specific PID when checking another process.10
| Check | Effect |
|---|---|
Launcher's NoNewPrivs |
A value of 1 prevents gaining new privileges through file capabilities |
nosuid on the executable's mount |
File capabilities are not applied at execution |
Launcher's CapBnd |
Limits capabilities obtainable at execution |
| Rebuilding or replacing the executable | File capabilities may not survive; check again |
Inspect the launcher's /proc/<pid>/status for NoNewPrivs and CapBnd.
Inspect mount options on the filesystem containing the collector's
executable. Execution restrictions can also cause startup
itself to fail with Operation not permitted, before any procfs
read.1210
Granting capabilities to a general-purpose interpreter such as a shell or Python extends privileges to the programs it can execute. Limit capability grants to the collection executable and check its ownership and write permissions.
Check namespace visibility and host restrictions
A capability held inside a container does not necessarily authorize the same operation on a host process. Check the relationship between the reader's and target's user namespaces. PID namespaces also affect which PIDs are visible: the target must exist in the reader's procfs view.138
hidepid may restrict other users' process information, and AppArmor or
SELinux policies may deny access. Inspect procfs mount options and host
audit logs before adding capabilities.82
Record the path and operation for each failure. Distinguish permission
errors such as EACCES and EPERM from errors such as ENOENT caused by
a disappearing process or path. This helps determine whether additional
permissions would address the failure.
Treat Docker API permissions separately
Reading host procfs and accessing the Docker API require separate permissions. The measurement collector also uses the Docker API to obtain containers and their PIDs.17
When the socket is used to obtain containers or PIDs from a conventional rootful Docker Engine, access can itself permit root-level operations on the host. A collector that sends only GET requests does not make its socket access read-only.14
References
This article is based on information verified as of September 17, 2026. The four-condition table is based on the September 12 measurement using the Go collector.
KestreLynx is open-source software that regularly scans images used by running Docker and Kubernetes containers with Trivy and sends changes since the last scan and priorities based on severity, CISA KEV, and EPSS to Slack or a webhook. For Docker and Compose, remediation plans and pull requests (experimental) support remediation from comparing update candidates to creating GitHub pull requests, with both features disabled by default. Users handle merging, rebuilding, and deployment.