Read and Set Linux User Namespace ID Maps Safely
You will finish able to inspect /proc/<pid>/uid_map and gid_map, read their three fields correctly, and recognise the rules that make a new mapping valid. The examples use the Linux man-pages 6.7 documentation installed with the manpages package, and the mapping files available since Linux 3.5.
The route
Jump straight to the step you need, or tick off Done means at the end.
Allow about fifteen minutes. You need a Linux shell and the unshare utility for the optional namespace test. Reading the files is normally unprivileged. Writing a mapping is a security-sensitive operation performed during namespace setup, so do not experiment against a service or a process you do not own.
1. Inspect the mapping for your shell
Start with the initial user namespace. This is read-only and does not require sudo:
$ cat /proc/$$/uid_map
0 0 4294967295
$ cat /proc/$$/gid_map
0 0 4294967295
Spacing is not significant. Each line contains three decimal numbers: the first is the start of a range inside the namespace belonging to the process, the second is the start of the corresponding range in the parent namespace, and the third is the range length. The initial namespace has no parent, but Linux exposes this dummy full-range view for consistency. The final value is 4294967295 rather than 4294967296, leaving the 32-bit value used as an invalid ID marker unmapped.
Checkpoint: if your output has one line beginning with three zero-and-range fields, you have confirmed that you are reading the mapping of the shell that opened the file. A different process can see different second-column values when it reads a process in another namespace.
2. Read a real mapping without changing it
For a process you own, substitute its numeric PID. This only reads the files:
$ PID=12345
$ test -r "/proc/$PID/uid_map" && cat "/proc/$PID/uid_map"
$ test -r "/proc/$PID/gid_map" && cat "/proc/$PID/gid_map"
A line such as 0 100000 65536 means that namespace IDs 0 through 65535 correspond to parent IDs 100000 through 165535. It does not mean that the host process has UID 0. System calls report IDs mapped into the caller's namespace, while file permission checks ultimately map credentials towards the initial namespace.
Do not infer a mapping from a container image, a username, or a process name. Read the target file. If the file is empty, the new namespace has not yet been mapped, and many operations that need credentials will not work.
3. Create a disposable namespace test
If your host permits unprivileged user namespaces, unshare -Ur asks util-linux to create one and arrange a root identity mapping for the test shell. It changes no persistent file, service or host account:
$ unshare -Ur sh -c 'printf "inside uid: %s\n" "$(id -u)"; cat /proc/self/uid_map; printf "inside gid: %s\n" "$(id -g)"; cat /proc/self/gid_map'
inside uid: 0
0 1000 1
inside gid: 0
0 1000 1
The numeric parent ID in this output is host-specific. It is only an example, not a value to copy. The command may fail with "Operation not permitted" when user namespaces are disabled or restricted by the kernel, container runtime or security policy. That failure does not justify enabling them on a production host. Record the error and use an existing namespace for inspection instead.
4. Understand the one-write boundary
After a user namespace is created, one process in it may write its uid_map once. A second write fails with EPERM. The same one-write rule applies to gid_map. A mapping write must contain at least one line, three valid numbers per line, a positive length, and newline-terminated records.
Ranges may not overlap. Since Linux 4.15 the file accepts up to 340 lines, and the complete write must be smaller than one page and start at offset zero. These limits matter to programs constructing maps, not to ordinary cat inspection. A malformed or overlapping map normally fails with EINVAL.
Permissions are stricter than ordinary file ownership. The writer needs CAP_SETUID for uid_map, or CAP_SETGID for gid_map, in the target process's user namespace. The writer must be in that namespace or its parent, and the mapped IDs must themselves be mapped in the parent. Since Linux 5.12, mappings that include parent UID 0 also require the relevant CAP_SETFCAP condition.
5. Treat group mappings as a separate trap
UID and GID files have the same three-field format, but group setup has an extra restriction for the unprivileged case. Before writing gid_map, the process may need to write deny to the new process's /proc/<pid>/setgroups file. This prevents later setgroups(2) use and is part of the kernel's permission rules, not a cosmetic preparation step.
Do not paste a mapping command from a container guide into a live workload without checking its namespace ownership, capabilities and rollback plan. A failed mapping write is recoverable before the one successful write, but a valid write cannot be replaced by editing the file. To undo a disposable test, exit the shell and let its namespace process terminate. Persistent container configuration must be reverted in the tool that created it.
Done means
- You can distinguish namespace IDs, parent IDs and range length.
- You inspected both mapping files without using elevated privileges.
- You know that an empty map is an unconfigured namespace, not a full mapping.
- You understand the one-write, non-overlap and capability rules.
- You can treat an
unsharepermission failure as a host policy boundary. - You did not alter a service, account, persistent configuration or host mapping.