Home / Alt manpages / proc(5)

  • proc(5)
  • File format
  • linux

Read /proc Safely and Restrict It with hidepid

/proc is a live window into every running process, and hidepid decides how much of it strangers can see. This guide shows how to read your own corner of it safely, check a kernel setting, and understand hidepid before you ever change what other users can see. The examples match the installed proc(5) from Linux man-pages 6.7 on a 6.8.0-139-generic kernel. Budget fifteen minutes: most of this is unprivileged, but the mount test needs root and touches the current mount namespace.

This is deliberately about inspection and one reversible test. It does not edit boot configuration, create a permanent fstab entry, or hand out broad access through sudo.

1. Confirm the proc filesystem and its mount options

Start with read-only checks. findmnt shows where proc is mounted and which options are live:

$ findmnt --target /proc --output TARGET,FSTYPE,OPTIONS
TARGET FSTYPE OPTIONS
/proc  proc   rw,nosuid,nodev,noexec,relatime

$ ls -ld /proc/self /proc/thread-self
lrwxrwxrwx ... /proc/self -> ...
lrwxrwxrwx ... /proc/thread-self -> ...

Your exact option list and link targets will differ. What matters is that the filesystem type is proc, and that /proc/self is a magic link to the calling process's own directory. /proc/thread-self resolves to the calling thread instead, which matters once a program is multithreaded.

Checkpoint

If findmnt reports no target at all, do not create a second mount just to make these examples run. Check the host's namespace and container setup first.

2. Read process data through /proc/self

Use /proc/self instead of guessing your shell's PID. That sidesteps a race where a stored PID has moved on to a different process by the time you read it:

$ sed -n '1,12p' /proc/self/status
Name:   sed
Umask:  0022
State:  R (running)
Tgid:   ...
Ngid:   0
Pid:    ...
PPid:   ...

Field order and values depend on the kernel, so never parse by fixed line number in anything long-lived. Pull a named field instead:

$ awk -F: '$1 == "Name" || $1 == "Pid" || $1 == "Uid" {print}' /proc/self/status
Name:   awk
Pid:    ...
Uid:    ...

Notice which command shows up: it is sed in the first example and awk in the second, because /proc/self always describes the process doing the reading. That is expected, and it is a classic source of a misleading test.

3. Handle null-separated proc files correctly

Some proc files, command-line and environment data included, separate fields with null bytes rather than newlines. On a terminal that can look like one mangled line. Convert nulls to newlines for inspection, without ever writing back to the file:

$ tr '\000' '\n' < /proc/self/cmdline
tr
\000\000

$ tr '\000' '\n' < /proc/self/environ | sed -n '1,5p'
SHELL=/bin/bash
...

The command name and arguments are process data, not a stable configuration interface. Environment values can hold secrets, so keep this output out of logs and support tickets. The redirection is read-only throughout; the \000 you see is a shell representation of a null byte, not something to write into /proc.

4. Inspect a sysctl file before you go near changing it

Some files under /proc/sys expose kernel variables, and some of those are writable. Read one first and record its current value:

$ printf 'hostname: '
$ cat /proc/sys/kernel/hostname
hostname: server.example.com

Reading needs no elevated privileges. Do not assume every file under /proc/sys is writable, or that a value means the same thing on a different kernel. If you do need to change a sysctl, use the documented setting plus an explicit rollback value: a write can take effect on the running system immediately and may not even survive a reboot.

Warning

This guide does not write a sysctl, and neither should you as a test. Do not run echo VALUE > /proc/sys/... on a production host until you have identified the setting, its effect, and the value that gets you back.

5. Understand hidepid before you test it

hidepid controls who can see into /proc/PID directories. The default, hidepid=0, keeps the traditional wide-open visibility.

  • hidepid=1 leaves process directories visible but locks down files and subdirectories belonging to other users.
  • hidepid=2 goes further and hides other users' process directories entirely when /proc is listed.

That distinction matters: hidepid=2 makes process discovery harder, but it does not make a process unknowable. The manual is explicit that other mechanisms, such as probing a PID with kill -0, can still reveal that it exists. Treat this as reduced local information exposure, not a complete isolation boundary.

You can name a group with gid=GROUP, and its members get access as though hidepid=0 still applied. The manual recommends this targeted exception over putting non-root users in sudoers.

6. Test hidepid in a throwaway mount namespace

Changing the host's real proc mount can break monitoring and process-management tools stone dead, so use a disposable mount namespace if your host allows it. This needs root and only ever changes the namespace created for this one shell:

$ sudo unshare --mount --fork sh
# mount --make-rprivate /
# mount -o remount,hidepid=2 /proc
# findmnt --target /proc --output TARGET,FSTYPE,OPTIONS
TARGET FSTYPE OPTIONS
/proc  proc   rw,nosuid,nodev,noexec,relatime,hidepid=2
# ls /proc | head
1
self
thread-self
# exit

The exact process list depends on the namespace and kernel. mount --make-rprivate / stops mount events propagating back to the host, and the remount only touches the proc instance already visible inside that namespace; it is not a permanent change.

Before running any of this, make sure unshare is actually available and that you understand the host's container and namespace policy. If unshare gets refused, stop there. Do not work around that refusal by remounting the host's real /proc as root.

Checkpoint

After exit, confirm the original mount is unchanged.

$ findmnt --target /proc --output TARGET,FSTYPE,OPTIONS
TARGET FSTYPE OPTIONS
/proc  proc   rw,nosuid,nodev,noexec,relatime

Common traps

  • Wrong command name in /proc/self? It follows whichever process is doing the read. Use a small helper command and read the output with that in mind.
  • Another user's files went unreadable after hidepid=1? That is the intended effect. Reach for the dedicated gid exception and its membership list rather than handing out sudo casually.
  • Process directories vanished under hidepid=2? Any tool that enumerates /proc may now see incomplete data. Test monitoring, service supervision and diagnostics before you consider deploying this for real.
  • Proc file full of odd separators? Check the manual's null-byte note and transform a copy for display. Never treat what you see on screen as the on-disk storage format.

Done means

  • Confirmed the active proc mount with findmnt.
  • Used /proc/self instead of trusting a stale PID.
  • Displayed null-separated data safely and kept environment values private.
  • Told apart hidepid=1 and hidepid=2, and understood their limits.
  • Tested a remount in a private namespace, or noted why the host policy refused it.
  • Left the host's real proc mount unchanged after the test.