the Chromium logo

The Chromium Projects

CrOS user & group management

In accordance with Gentoo's GLEP 27, ChromiumOS centrally manages its users & groups so they are stable for a given build profile.

Account Database

Each user and group is defined in a file underneath the appropriate profiles/base/accounts/ subdirectory in the eclass-overlay.

For example, the chronos user is defined as follows in a file at profiles/base/accounts/user/chronos:

user:chronos
password:*
uid:1000
gid:1000
gecos:system_user
home:/home/chronos/user
shell:/bin/bash

The cras group is defined in a similarly constructed file at profiles/base/accounts/group/cras:

group:cras
password:!
gid:220
users:chronos,power

Notice how the membership of the group is provided in the group definition, even though traditionally this is done at user-creation time.

The password field can be set to one of the following:

No longer needed UIDs/GIDs

When a UID or GID is no longer needed, the account database entry needs to remain to prevent the UID/GID from being accidentally reused. Re-using the UID/GID could lead to a number of problems especially if there are left over files owned by the UID/GID.

To mark a UID or GID as no longer used, add defunct:true to the end of the database entry file. For example:

user:tpmd
uid:225
gid:225
gecos:TPM daemon
home:/dev/null
shell:/bin/false
defunct:true

Choosing UIDs and GIDs

Every UID on CrOS has an associated GID with the same value. The opposite does not hold true, however.

CrOS system daemon UIDs (and associated GIDs) range from 200-299 and from 20100-29999. If you're creating a new user, pick the first UID in the range 20100-29999 that is not currently used, and create both a user and a group with this ID. To find the next available UID, invoke ./display-accts.py --show-free (found in the profiles/base/accounts/ subdirectory in the eclass-overlay).

FUSE-based filesystem daemons have UID/GIDs that range from 300-399. If you're adding a daemon that will be talking to cros-disks and managing some kind of volumes (archives mounted as volumes, external disks, network-mounted storage, etc.) then you should create a user and group with IDs in this range.

Groups that have no associated user should be given GIDs in the 400 range.

Groups and users that are shared with programs running in different user namespaces should be in the 600-699 range.

The chronos user, which all user-facing processes in CrOS run as, is UID/GID 1000. There is also a special user/group that has access to many resources owned by chronos, called chronos-access, which has the UID/GID 1001.

Testing

Note: This step is not necessary for self-groups (groups which only contain their corresponding user).

If a new group has users, matching baselines must be added to chromite's cros/test/usergroup_baseline.py:

GroupEntry(group='cras', gid=220, users={'chronos', 'power'}),

Board/project-specific accounts

For boards creating their own users, the 2000-4999 range is reserved for that. Boards must take care that they don't create conflicts amongst themselves or any project overlays they inherit.

This space is not intended for mainline CrOS use. Such projects should be integrated directly into this overlay instead. This is only for boards/projects that are maintained by partners.

Creating users and groups in ebuilds

There are two ways to add accounts to the system. The new way (acct-group & acct-user packages), is ready to use, but we haven't migrated existing code to it, so the old way (user.eclass) is still used quite a bit. Developers should use the new system when writing new ebuilds.

The two systems are compatible, and accounts can be safely declared & created by both simultaneously, so migration should be easy.

acct-group & acct-user

For accounts that exist in upstream Gentoo, the cros_portage_upgrade tool can be used to quickly import packages. Keep in mind these will be imported to the portage-stable overlay by default, so they will have to be manually moved to the eclass-overlay instead.

In the eclass-overlay, create a package for the user in the acct-user category, and a package for the group in the acct-group category.

The ebuilds are largely stubs as the business logic is handled by our custom acct-group.eclass & acct-user.eclass eclasses. Keep in mind that the values set in the ebuild are currently ignored (e.g. UID & GID), and instead are taken from the profiles/base/accounts/ database instead.

Here is an example acct-user/sshd:

# Copyright 2020 Gentoo Authors
# Distributed under the terms of the GNU General Public License v2

EAPI=7

inherit acct-user

DESCRIPTION="User for ssh"

# NB: These settings are ignored in CrOS for now.
# See the files in profiles/base/accounts/ instead.

ACCT_USER_ID=22

Here is an example acct-group/sshd:

# Copyright 2020 Gentoo Authors
# Distributed under the terms of the GNU General Public License v2

EAPI=7

inherit acct-group

# NB: These settings are ignored in CrOS for now.
# See the files in profiles/base/accounts/ instead.

ACCT_GROUP_ID=22

With those packages in place, the ebuild that wants the accounts available at runtime just adds them to their RDEPEND.

RDEPEND+="
	acct-group/sshd
	acct-user/sshd
"

user.eclass (the old way)

The API implemented by the CrOS-specific user.eclass is compatible with the one that historically was provided by the upstream user.eclass.

enewuser cras   # Creates a user called 'cras' with the pre-specified UID.
enewgroup cras  # Ditto for the group.

You can choose to specify other fields when calling the functions to create new users and groups, but the eclass will bail if the values you choose conflict with those in the DB.

Calls to enewuser and enewgroup are allowed ONLY in three ebuild stanzas:

Bear in mind that when creating a new user, simply using cros deploy to install the new package on the test system will not install the new user. This is discussed in crbug.com/402673. You can build a new image (by using emerge-$BOARD <package> and cros build-image) to get the new user/group to show up in /etc/passwd and /etc/group.

Alternatively you can emerge-$BOARD the package with the new user/group and then copy /build/$BOARD/etc/{passwd,group} over the device's /etc/{passwd,group}, via scp or some other mechanism.

FAQ

User/group not showing up in newly built image!

Defining an account in the profiles/base/accounts/ databases is not sufficient to actually create the account at runtime. By design, CrOS only creates accounts that are used by packages that are installed into the rootfs. So if no installed package creates those accounts, they won't show up in the image.

Deploying packages via 'cros deploy' are missing accounts!

Currently the account databases are created only when the image is initially created. Trying to deploy new ones on the fly won't work. You can workaround it by manually editing the /etc/passwd & /etc/group files to add the accounts, or creating the image.