proc_pid_root(5)
๐ proc_pid_root(5) ๐
okay bestie, welcome to the File Formats Manual entry for proc_pid_root(5) โ yes, one entire man page for what looks like one little symlink, and honestly? it's giving main character energy and it deserves it. let's go ๐
โจ NAME โจ
/proc/pid/root/โ symbolic link to root directory ๐ฆ
๐ธ DESCRIPTION ๐ธ
/proc/pid/root/
okay so here's the vibe: UNIX and Linux support the idea of a per-process root of the filesystem, and that whole thing gets set by the chroot(2) system call. This file is a symbolic link that points to the process's root directory, and it behaves in the same way as exe, and fd/*. no cap ๐ฅ
but wait. this file is not merely a symbolic link ๐ญ it's so much more than that.
It provides the same view of the filesystem (including namespaces and the set of per-process mounts) as the process itself. like, the whole filesystem how that process sees it. an example illustrates this point, so buckle up:
In one terminal, we start a shell in new user and mount namespaces, and in that shell we create some new mounts:
$ PS1='sh1# ' unshare -Urnm;
sh1# mount -t tmpfs tmpfs /etc; # Mount empty tmpfs at /etc
sh1# mount --bind /usr /dev; # Mount /usr at /dev
sh1# echo $$;
27123
In a second terminal window, in the initial mount namespace, we look at the contents of the corresponding mounts in the initial and new namespaces:
$ PS1='sh2# ' sudo sh;
sh2# ls /etc | wc -l; # In initial NS
309
sh2# ls /proc/27123/root/etc | wc -l; # /etc in other NS
0 # The empty tmpfs dir
sh2# ls /dev | wc -l; # In initial NS
205
sh2# ls /proc/27123/root/dev | wc -l; # /dev in other NS
11 # Actually bind
# mounted to /usr
sh2# ls /usr | wc -l; # /usr in initial NS
11
see how the counts are completely different depending on whose root you're peeking through? that's the whole point, bestie. the same /etc is 309 entries one way and 0 the other way, because in the other namespace /etc is an empty tmpfs. iconic.
Now for the sad part ๐ In a multithreaded process, the contents of the /proc/pid/root symbolic link are not available if the main thread has already terminated (typically by calling pthread_exit(3)). so if your main thread dipped, that link is just... not there. ๐ญ
Also: permission to dereference or read (readlink(2)) this symbolic link is governed by a ptrace access mode PTRACE_MODE_READ_FSCREDS check; see ptrace(2). don't skip the vibe check, basically ๐
๐ SEE ALSO ๐
proc(5)โ go read it, iykyk ๐
and that's the whole page, bestie!! ๐ซถ this was written up in the Linux man-pages 6.20 release, dated 2026-02-08, and it lives at proc_pid_root(5). mwah, slay, periodt โจ๐
๐ฆ where this page comes from
- arch rolling: man-pages 6.20-1 ยท BSD-2-Clause AND BSD-3-Clause AND BSD-4.3TAHOE AND BSD-4-Clause-UC AND GPL-1.0-or-later AND GPL-2.0-only AND GPL-2.0-or-later AND GPL-3.0-or-later AND LGPL-3.0-linking-exception AND LGPL-3.0-or-later AND LicenseRef-Public-Domain AND LicenseRef-UltraPermissive AND Linux-man-pages-1-para AND Linux-man-pages-copyleft AND Linux-man-pages-copyleft-2-para AND Linux-man-pages-copyleft-var AND MIT AND Spencer-94
- nixpkgs unstable: man-pages 6.20
- ๐ the page's license: GPL-3.0-or-later
- Copyright 1994-1995, Daniel Quinlan <Daniel.Quinlan@linux.org>
- Copyright 2002-2017, Michael Kerrisk <mtk.manpages@gmail.com>
- ๐ girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms