Home / Alt manpages / proc_pid_gid_map(5)

  • proc_pid_gid_map(5)
  • File format
  • linux

Read a User Namespace's gid_map in /proc

A process inside a container reports group 0, yet its files land on disk owned by an ordinary group: /proc/PID/gid_map is why. The examples use Linux man-pages 6.7, installed here as package version 6.7-2.

Allow about fifteen minutes. You need a shell with /proc mounted and the util-linux unshare command for the optional namespace test.

  • Reading an existing map is ordinary, unprivileged work.
  • Creating a namespace or writing a map changes process state. Test only with a short-lived child, never inside a live service.

1. Inspect the map for your current shell

Replace PID with a process ID when you are investigating another process. For the current shell, $$ is the shell's own PID:

$ cat /proc/$$/gid_map
         0          0 4294967295

The three columns are, in order, the first group ID in the process's user namespace, the first group ID in the parent or viewing namespace, and the length of the contiguous range. This line maps almost the complete 32-bit group-ID space starting at zero. The value 4294967295 is deliberately included: the unsigned 32-bit representation of (gid_t)-1, used by several interfaces to mean "no group ID".

Checkpoint

Record the exact PID and map before drawing conclusions. A process can be in a different user namespace from your shell, and the values shown depend on the namespace of the process that opened the file.

2. Check both UID and GID maps together

gid_map is the group-ID counterpart of uid_map. A paired check often explains a failure faster than looking at one file alone:

$ printf 'uid_map: '; cat /proc/$$/uid_map
uid_map:          0          0 4294967295
$ printf 'gid_map: '; cat /proc/$$/gid_map
gid_map:          0          0 4294967295

The labels above are not part of the proc file output; they come from printf. The file itself contains whitespace-separated numbers and newline-terminated mapping records.

System calls such as getgid(2) return a group ID mapped into the caller's user namespace. File ownership checks work the other way: the process's credentials are mapped towards the initial user namespace when the kernel checks a file. A group ID that reads 0 inside a namespace is therefore not automatically the host's group ID 0.

3. Create a disposable namespace, if the host allows it

This command asks unshare to create a user namespace and run a shell in it. It makes no persistent configuration change, but kernel or container policy may forbid unprivileged user namespaces. Start without sudo, this is meant to be an ordinary command:

$ unshare --user --map-root-user sh -c 'cat /proc/self/uid_map; cat /proc/self/gid_map; id'
         0       1004          1
         0       1004          1
uid=0(root) gid=0(root) groups=0(root)

The displayed host ID is an example. On a machine that permits the operation, --map-root-user arranges a one-line identity mapping for the invoking user, and the child sees that mapped identity as ID 0. Exact whitespace and account names can differ.

If you get Operation not permitted, stop there. It commonly means user namespaces are disabled or restricted by the host, container runtime or security policy, not that /proc/PID/gid_map is malformed. Do not work around the restriction with elevated privileges unless you administer the host and have a specific reason.

Checkpoint

If the child starts, save its PID from inside the child when you need to inspect it from another shell. Otherwise inspect its maps before the command exits, since the process and its proc entries disappear when it finishes.

4. Understand what a writable map permits

A newly created user namespace starts with no UID or GID mapping. The map for one process in that namespace can be written once to define it. A successful map has at least one line, positive range lengths, non-overlapping ranges, and a write smaller than the system page size performed at the start of the file. Linux 4.15 and later permit up to 340 lines; Linux 4.14 and earlier used a five-line limit.

  • CAP_SETGID is required. The writer needs that capability and must be in the child user namespace or its parent, and the target group IDs must already be mapped in the parent.
  • No parent capability means one fallback line. If the writer lacks the parent capability, the only permitted write is one line mapping the writer's own effective group ID, and setgroups(2) must first be disabled by writing deny to /proc/PID/setgroups.
  • Since Linux 5.12, mappings that map parent UID 0 also need CAP_SETFCAP. That is a UID rule, but it matters whenever you configure both maps for a container-like workload.

Warning

The deny write to setgroups is permanent for the user namespace. Treat it as an intentional security boundary, not a routine troubleshooting command. There is no undo; the child namespace must be recreated if the choice was wrong.

5. Diagnose the usual read and write failures

  • Empty map. The namespace has not received a mapping yet, and calls that change group IDs will fail until a valid GID map exists.
  • EPERM. Usually means the writer is in the wrong namespace, lacks the required capability, or is attempting a second write. Check the process namespace and credentials before changing the map.
  • EINVAL. Points to invalid map data: a non-positive length, overlapping ranges, no newline-terminated record, too many bytes, or a write that did not start at offset zero.
  • Permission error opening another process's map. Can be caused by proc ownership and dumpability, especially after an effective-ID change. Inspect the target process and its namespace rather than guessing a different mapping.

For a read-only comparison, check the namespace identity as well as the map:

$ readlink /proc/$$/ns/user
user:[4026531837]
$ cat /proc/$$/gid_map
         0          0 4294967295

The namespace inode is host-specific. Compare it with readlink /proc/PID/ns/user for the process you are investigating; equal values mean membership in the same user namespace.

Done means

  • Read the three fields in /proc/PID/gid_map in the correct order.
  • Checked uid_map alongside gid_map when investigating credentials.
  • Know whether this host permits an unprivileged disposable user namespace.
  • Can distinguish an empty map, invalid data and insufficient mapping permissions.
  • Changed nothing persistent: no file, service or existing namespace, and you know setgroups denial cannot be undone inside a namespace.