Inspect and map project IDs with /proc/pid/projid_map
You will read the project-ID mapping for a process, identify the namespace it belongs to, and understand the checks that govern a mapping write. Project IDs are used by Linux disk quotas. They are not the same thing as user IDs, group IDs or ordinary process IDs.
The route
Jump straight to the step you need, or tick off Done means at the end.
Allow about fifteen minutes. You need a shell and a Linux system with procfs mounted. The examples below use Linux 6.8 and Linux man-pages 6.7 as installed on this machine. The file has existed since Linux 3.7, but namespace and quota configuration can make the result different on another host. Reading the file is unprivileged when the relevant /proc entry is readable. Do not use sudo as a first response to a mapping error.
1. Read your own project-ID map
Start with the process running your shell. The special path /proc/self follows the process that opens it, so it avoids guessing a PID:
$ cat /proc/self/projid_map
0 0 4294967295
Each line has three decimal values: a project-ID range inside the process's user namespace, the corresponding range in its parent user namespace, and the number of consecutive IDs in the range. In this output, the whole 32-bit project-ID range is mapped to the same range. The spacing is formatting, not data that your script should parse by column position.
Checkpoint: capture the file as data, then count its fields rather than relying on visual alignment:
awk 'NF { print "inside=" $1, "parent=" $2, "length=" $3 }' /proc/self/projid_map
A process in a newly created user namespace may show no mapping until its parent has written one. An empty file is therefore a meaningful namespace state, not proof that procfs is broken.
2. Inspect another process without changing it
Replace PID with a real process ID. The ordinary read-only commands below need no elevated privileges:
$ PID=12345
$ test -r "/proc/$PID/projid_map" && cat "/proc/$PID/projid_map"
0 0 4294967295
Use a process that is still running. A missing path usually means that the PID exited between commands, not that the mapping file is optional for a live process. If the test fails, inspect the directory and process status without altering anything:
$ ps -p "$PID" -o pid=,user=,comm=
$ ls -l "/proc/$PID/projid_map"
ls: cannot access '/proc/12345/projid_map': Permission denied
The exact error depends on the host's procfs mount options, process ownership and security policy. Reading a different user's process may require elevated privilege, but access as root still does not let you ignore the mapping rules described below.
3. Interpret the namespace boundary
The file belongs to the user namespace of PID. A project-ID mapping translates IDs seen inside that namespace to IDs in its parent namespace. It is useful when a quota-aware operation needs project IDs to survive a user-namespace boundary. It does not grant quota control by itself, and writing this file does not configure a filesystem quota. Quota administration remains a separate task using the filesystem's quota support.
The installed user_namespaces(7) manual gives the validity rule: a mapping must use non-overlapping ranges, and the ranges must fit the relevant project-ID space. Violating a validity rule makes the write(2) fail with EINVAL. Keep the first two columns in the same coordinate order: inside the target namespace first, then the parent namespace.
Do not confuse this file with uid_map or gid_map. Those map user and group IDs. projid_map maps project IDs used by disk quotas. A line copied from a UID mapping may be syntactically shaped like a project mapping while being operationally wrong for your quota design.
4. Check who may write the map
Writing is a security-sensitive namespace operation. Stop before the write if you are not deliberately creating or configuring a user namespace. The writer must be in the target process's user namespace or in its parent user namespace. Every project ID being mapped must itself have a mapping in the parent namespace. These are permission rules, so violating them makes write(2) fail with EPERM.
The target map is normally written by the parent after it creates a child in a new user namespace. A representative payload for one project ID is:
$ printf '%s\n' '1000 1000 1'
1000 1000 1
This only prints the proposed line. It does not change the kernel. Do not redirect it into an existing process's mapping file as an experiment. Mapping files are namespace setup interfaces, and a failed or incorrect write can stop the namespace setup you intended to perform. A mapping is also not a quota grant: the filesystem quota configuration must already make sense for the mapped project ID.
5. Test namespace tooling without assuming it will work
A user-namespace helper may create the target namespace and arrange the user mappings before your command runs. Check which implementation and version you will invoke:
$ command -v unshare
/home/linuxbrew/.linuxbrew/bin/unshare
$ unshare --version
unshare from util-linux 2.41.3
Then use a harmless read-only probe. This does not write projid_map:
$ unshare --user --map-root-user sh -c 'cat /proc/self/projid_map'
unshare: write failed /proc/self/uid_map: Operation not permitted
On this machine the probe is blocked while unshare tries to write uid_map. On another host it may reach the project-ID read, or it may fail for the same reason. User namespaces can be restricted by the kernel, container runtime or security policy. That failure is a host capability boundary, not evidence that the project-ID file has a bad format. Do not weaken container or kernel security settings merely to run a demonstration.
If you are implementing a real mapping workflow, record the creator, target PID, user namespace and parent namespace together. A PID can be reused after a process exits, so a bare PID in a long-running script is not a durable identity. Re-open the procfs path immediately before inspection and handle disappearance as a race.
6. Diagnose a failed write
Use the error class to choose the next check:
EINVALpoints to the payload or mapping validity: check decimal values, range length, overlap and namespace coordinate order.EPERMpoints to the writer's namespace or to a project ID that is not mapped in the parent namespace.ENOENTor a disappearing procfs path usually means that the target process ended; create a fresh namespace and do not reuse the old PID.EACCESwhile reading points to procfs visibility or access policy, not necessarily to an invalid map.
After a successful setup, read the target's mapping again and verify the exact line rather than trusting a zero exit status from a wrapper. Keep the namespace process alive while checking it. Once it exits, its /proc/$PID files disappear and the mapping is gone with the namespace.
Done means
- You can read
/proc/self/projid_mapand explain all three columns. - You distinguish project IDs from user IDs, group IDs and process IDs.
- You know the file describes a user-namespace mapping, not a filesystem quota grant.
- You test a proposed line by printing it first and do not write to an unrelated live process.
- You can separate
EINVAL,EPERM, process-race failures and read access failures.