]> git.ipfire.org Git - thirdparty/systemd.git/blame - UIDS-GIDS.md
core: use id unit when retrieving unit file state (#8038)
[thirdparty/systemd.git] / UIDS-GIDS.md
CommitLineData
39972553
LP
1# Users, Groups, UIDs and GIDs on `systemd` systems
2
3Here's a summary of the requirements `systemd` (and Linux) make on UID/GID
4assignments and their ranges.
5
6Note that while in theory UIDs and GIDs are orthogonal concepts they really
7aren't IRL. With that in mind, when we discuss UIDs below it should be assumed
8that whatever we say about UIDs applies to GIDs in mostly the same way, and all
9the special assignments and ranges for UIDs always have mostly the same
10validity for GIDs too.
11
12## Special Linux UIDs
13
14In theory, the range of the C type `uid_t` is 32bit wide on Linux,
15i.e. 0…4294967295. However, four UIDs are special on Linux:
16
171. 0 → The `root` super-user
18
192. 65534 → The `nobody` UID, also called the "overflow" UID or similar. It's
2e276b1d
LP
20 where various subsystems map unmappable users to, for example file systems
21 only supporting 16bit UIDs, NFS or user namespacing. (The latter can be
22 changed with a sysctl during runtime, but that's not supported on
23 `systemd`. If you do change it you void your warranty.) Because Fedora is a
24 bit confused the `nobody` user is called `nfsnobody` there (and they have a
25 different `nobody` user at UID 99). I hope this will be corrected eventually
26 though. (Also, some distributions call the `nobody` group `nogroup`. I wish
27 they didn't.)
39972553
LP
28
293. 4294967295, aka "32bit `(uid_t) -1`" → This UID is not a valid user ID, as
9e4b8893
LP
30 `setresuid()`, `chown()` and friends treat -1 as a special request to not
31 change the UID of the process/file. This UID is hence not available for
32 assignment to users in the user database.
39972553 33
9e4b8893
LP
344. 65535, aka "16bit `(uid_t) -1`" → Before Linux kernel 2.4 `uid_t` used to be
35 16bit, and programs compiled for that would hence assume that `(uid_t) -1`
36 is 65535. This UID is hence not usable either.
39972553
LP
37
38The `nss-systemd` glibc NSS module will synthesize user database records for
39the UIDs 0 and 65534 if the system user database doesn't list them. This means
40that any system where this module is enabled works to some minimal level
41without `/etc/passwd`.
42
43## Special Distribution UID ranges
44
45Distributions generally split the available UID range in two:
46
471. 1…999 → System users. These are users that do not map to actual "human"
48 users, but are used as security identities for system daemons, to implement
49 privilege separation and run system daemons with minimal privileges.
50
512. 1000…65533 and 65536…4294967294 → Everything else, i.e. regular (human) users.
52
53Note that most distributions allow changing the boundary between system and
54regular users, even during runtime as user configuration. Moreover, some older
55systems placed the boundary at 499/500, or even 99/100. In `systemd`, the
56boundary is configurable only during compilation time, as this should be a
57decision for distribution builders, not for users. Moreover, we strongly
58discourage downstreams to change the boundary from the upstream default of
59999/1000.
60
61Also note that programs such as `adduser` tend to allocate from a subset of the
62available regular user range only, usually 1000..60000. And it's also usually
63user-configurable, too.
64
65Note that systemd requires that system users and groups are resolvable without
66networking available — a requirement that is not made for regular users. This
67means regular users may be stored in remote LDAP or NIS databases, but system
68users may not (except when there's a consistent local cache kept, that is
69available during earliest boot, including in the initial RAM disk).
70
71## Special `systemd` GIDs
72
73`systemd` defines no special UIDs beyond what Linux already defines (see
74above). However, it does define some special group/GID assignments, which are
75primarily used for `systemd-udevd`'s device management. The precise list of the
76currently defined groups is found in this `sysusers.d` snippet:
77[basic.conf](https://raw.githubusercontent.com/systemd/systemd/master/sysusers.d/basic.conf.in)
78
79It's strongly recommended that downstream distributions include these groups in
80their default group databases.
81
82Note that the actual GID numbers assigned to these groups do not have to be
83constant beyond a specific system. There's one exception however: the `tty`
84group must have the GID 5. That's because it must be encoded in the `devpts`
85mount parameters during earliest boot, at a time where NSS lookups are not
86possible. (Note that the actual GID can be changed during `systemd` build time,
87but downstreams are strongly advised against doing that.)
88
89## Special `systemd` UID ranges
90
91`systemd` defines a number of special UID ranges:
92
931. 61184…65519 → UIDs for dynamic users are allocated from this range (see the
94 `DynamicUser=` documentation in
95 [`systemd.exec(5)`](https://www.freedesktop.org/software/systemd/man/systemd.exec.html)). This
96 range has been chosen so that it is below the 16bit boundary (i.e. below
97 65535), in order to provide compatibility with container environments that
98 assign a 64K range of UIDs to containers using user namespacing. This range
99 is above the 60000 boundary, so that its allocations are unlikely to be
100 affected by `adduser` allocations (see above). And we leave some room
101 upwards for other purposes. (And if you wonder why precisely these numbers:
102 if you write them in hexadecimal, they might make more sense: 0xEF00 and
103 0xFFEF). The `nss-systemd` module will synthesize user records implicitly
104 for all currently allocated dynamic users from this range. Thus, NSS-based
105 user record resolving works correctly without those users being in
106 `/etc/passwd`.
107
1082. 524288…1879048191 → UID range for `systemd-nspawn`'s automatic allocation of
109 per-container UID ranges. When the `--private-users=pick` switch is used (or
110 `-U`) then it will automatically find a so far unused 16bit subrange of this
111 range and assign it to the container. The range is picked so that the upper
112 16bit of the 32bit UIDs are constant for all users of the container, while
113 the lower 16bit directly encode the 65536 UIDs assigned to the
114 container. This mode of allocation means that the upper 16bit of any UID
115 assigned to a container are kind of a "container ID", while the lower 16bit
116 directly expose the container's own UID numbers. If you wonder why precisely
117 these numbers, consider them in hexadecimal: 0x00080000…0x6FFFFFFF. This
118 range is above the 16bit boundary. Moreover it's below the 31bit boundary,
119 as some broken code (specifically: the kernel's `devpts` file system)
120 erroneously considers UIDs signed integers, and hence can't deal with values
121 above 2^31. The `nss-mymachines` glibc NSS module will synthesize user
122 database records for all UIDs assigned to a running container from this
123 range.
124
125Note for both allocation ranges: when an UID allocation takes place NSS is
126checked for collisions first, and a different UID is picked if an entry is
127found. Thus, the user database is used as synchronization mechanism to ensure
128exclusive ownership of UIDs and UID ranges. To ensure compatibility with other
129subsystems allocating from the same ranges it is hence essential that they
130ensure that whatever they pick shows up in the user/group databases, either by
131providing an NSS module, or by adding entries directly to `/etc/passwd` and
132`/etc/group`. For performance reasons, do note that `systemd-nspawn` will only
133do an NSS check for the first UID of the range it allocates, not all 65536 of
134them. Also note that while the allocation logic is operating, the glibc
135`lckpwdf()` user database lock is taken, in order to make this logic race-free.
136
137## Figuring out the system's UID boundaries
138
139The most important boundaries of the local system may be queried with
140`pkg-config`:
141
142```
143$ pkg-config --variable=systemuidmax systemd
144999
145$ pkg-config --variable=dynamicuidmin systemd
14661184
147$ pkg-config --variable=dynamicuidmax systemd
14865519
149$ pkg-config --variable=containeruidbasemin systemd
150524288
151$ pkg-config --variable=containeruidbasemax systemd
1521878982656
153```
154
155(Note that the latter encodes the maximum UID *base* `systemd-nspawn` might
156pick — given that 64K UIDs are assigned to each container according to this
157allocation logic, the maximum UID used for this range is hence
1581878982656+65535=1879048191.)
159
160Note that systemd does not make any of these values runtime-configurable. All
161these boundaries are chosen during build time. That said, the system UID/GID
162boundary is traditionally configured in /etc/login.defs, though systemd won't
163look there during runtime.
164
165## Considerations for container managers
166
167If you hack on a container manager, and wonder how and how many UIDs best to
168assign to your containers, here are a few recommendations:
169
1701. Definitely, don't assign less than 65536 UIDs/GIDs. After all the `nobody`
171user has magic properties, and hence should be available in your container, and
172given that it's assigned the UID 65534, you should really cover the full 16bit
173range in your container. Note that systemd will — as mentioned — synthesize
174user records for the `nobody` user, and assumes its availability in various
175other parts of its codebase, too, hence assigning fewer users means you lose
176compatibility with running systemd code inside your container. And most likely
177other packages make similar restrictions.
178
1792. While it's fine to assign more than 65536 UIDs/GIDs to a container, there's
180most likely not much value in doing so, as Linux distributions won't use the
181higher ranges by default (as mentioned neither `adduser` nor `systemd`'s
182dynamic user concept allocate from above the 16bit range). Unless you actively
183care for nested containers, it's hence probably a good idea to allocate exactly
18465536 UIDs per container, and neither less nor more. A pretty side-effect is
185that by doing so, you expose the same number of UIDs per container as Linux 2.2
186supported for the whole system, back in the days.
187
1883. Consider allocating UID ranges for containers so that the first UID you
189assign has the lower 16bits all set to zero. That way, the upper 16bits become
190a container ID of some kind, while the lower 16bits directly encode the
191internal container UID. This is the way `systemd-nspawn` allocates UID ranges
192(see above). Following this allocation logic ensures best compability with
193`systemd-nspawn` and all other container managers following the scheme, as it
194is sufficient then to check NSS for the first UID you pick regarding conflicts,
195as that's what they do, too. Moreover, it makes `chown()`ing container file
196system trees nicely robust to interruptions: as the external UID encodes the
197internal UID in a fixed way, it's very easy to adjust the container's base UID
198without the need to know the original base UID: to change the container base,
199just mask away the upper 16bit, and insert the upper 16bit of the new container
200base instead. Here are the easy conversions to derive the internal UID, the
201external UID, and the container base UID from each other:
202
203 ```
204 INTERNAL_UID = EXTERNAL_UID & 0x0000FFFF
205 CONTAINER_BASE_UID = EXTERNAL_UID & 0xFFFF0000
206 EXTERNAL_UID = INTERNAL_UID | CONTAINER_BASE_UID
207 ```
208
2094. When picking a UID range for containers, make sure to check NSS first, with
210a simple `getpwuid()` call: if there's already a user record for the first UID
211you want to pick, then it's already in use: pick a different one. Wrap that
212call in a `lckpwdf()` + `ulckpwdf()` pair, to make allocation
213race-free. Provide an NSS module that makes all UIDs you end up taking show up
214in the user database, and make sure that the NSS module returns up-to-date
215information before you release the lock, so that other system components can
216safely use the NSS user database as allocation check, too. Note that if you
217follow this scheme no changes to `/etc/passwd` need to be made, thus minimizing
218the artifacts the container manager persistently leaves in the system.
219
220## Summary
221
222| UID/GID | Purpose | Defined By | Listed in |
223|-----------------------|-----------------------|---------------|-------------------------------|
224| 0 | `root` user | Linux | `/etc/passwd` + `nss-systemd` |
225| 1…4 | System users | Distributions | `/etc/passwd` |
226| 5 | `tty` group | `systemd` | `/etc/passwd` |
227| 6…999 | System users | Distributions | `/etc/passwd` |
228| 1000…60000 | Regular users | Distributions | `/etc/passwd` + LDAP/NIS/… |
229| 60001…61183 | Unused | | |
230| 61184…65519 | Dynamic service users | `systemd` | `nss-systemd` |
231| 65520…65533 | Unused | | |
232| 65534 | `nobody` user | Linux | `/etc/passwd` + `nss-systemd` |
233| 65535 | 16bit `(uid_t) -1` | Linux | |
234| 65536…524287 | Unused | | |
235| 524288…1879048191 | Container UID ranges | `systemd` | `nss-mymachines` |
236| 1879048192…4294967294 | Unused | | |
237| 4294967295 | 32bit `(uid_t) -1` | Linux | |
238
239Note that "Unused" in the table above doesn't meant that these ranges are
240really unused. It just means that these ranges have no well-established
241pre-defined purposes between Linux, generic low-level distributions and
242`systemd`. There might very well be other packages that allocate from these
243ranges.