SELinux users and roles

June 02, 2021

In SELinux-enabled environments, the login binary calls the libselinux API to establish the initial mapping between SELinux users and local users. Then, after finding the right SELinux user, the system looks up the role and domain that the user should be in and sets that as the user’s context.

Listing SELinux user mappings

When logged in to the system, we can use id -Z to obtain the current SELinux context. For many users, this context will be defined by the unconfined user (unconfined_u), regardless of their username. If not that, it will generally be a context based on one of sysadm_u, staff_u, or user_u. This is because most Linux distributions will only provide a limited set of SELinux users by default, aligned with the SELinux roles that they support.

During login, the service process through which the login is handled will check a local definition file to find the appropriate mapping between the Linux account and the SELinux user. Let’s look at the existing login mappings using semanage login -l. The following output is the default output on a CentOS system:

# semanage login -l
Login Name		SELinux User	MLS/MCS Range	Service
__default__	unconfined_u	s0-s0:c0.c1023	*
root			unconfined_u	s0-s0:c0.c1023	*

The output of the command shows one login mapping per line. Each mapping consists of the following:

  • The Login Name for which the mapping is applicable (that is, the username)
  • The SELinux User to which the login is mapped
  • The MLS/MCS Range to which the login is mapped
  • The Service for which the mapping applies (this is used for local customizations, which we will tackle in the Customizing logins for services section)

The login name can contain a few special values that do not map directly to a single Linux account:

  • __default__ is a catch-all rule. If none of the other rules match, then the users are mapped to the SELinux user identified through this line. In the given example, all users are mapped to the unconfined_u SELinux user, meaning regular Linux users are hardly confined in their actions. When this isn’t meant to happen, administrators usually map regular logins to restricted SELinux users, while administrative logins are mapped to the staff_u or sysadm_u SELinux users.
  • Login names starting with % will map to groups. This allows administrators to map a group of people directly to an SELinux user rather than having to manage the mappings individually.

When both an individual user mapping and group mapping match, then the individual user mapping takes precedence. When multiple group definitions exist, then SELinux will use the first matching group mapping (in the order listed in the underlying seusers configuration file).


System processes (non-interactively logged-in Linux accounts) are mapped to the system_u SELinux user. This SELinux user should never be assigned to end user logins.

In the case of an MLS- or MCS-enabled system, the mapping contains information about the user’s allowed sensitivity range (MLS/MCS range). This way, we can map multiple users to the same restricted SELinux user, while differentiating between these users through the allowed sensitivities. For instance, one user might only be allowed to access low-sensitivity areas (s0), whereas another user might also have access to higher sensitivities (for example, s1) or different categories.

Mapping logins to SELinux users

Let’s use a few examples to show how we make these mappings work. For more intricate details on this, see the SELinux and PAM section. We’ll assume we have a Linux user called lisa, and we want her account to be mapped to the staff_u SELinux user, whereas all other users in the users group are mapped to the user_u SELinux user.

We can accomplish this through the semanage login command, using the -a (add) option:

# semanage login -a -s staff_u lisa
# semanage login -a -s user_u %users

The -s parameter assigns the SELinux user to the given login, whereas the -r parameter handles the sensitivity (and categories) for that user. For instance, let’s modify (using -m instead of -a) the recently created group-based definition by mapping to the staff_u user instead, and limiting these users to the s0-s0 sensitivity range and categories c0 to c4:

# semanage login -m -s staff_u -r "s0-s0:c0.c4" %users

The sensitivity range of a login mapping may not exceed the range assigned to the SELinux user. For example, if the staff_u SELinux user itself is only granted access to s0-s0:c0.c3, then the previous command will fail as it is trying to assign a broader access range. We’ll discuss how to define SELinux users and their range in the Creating SELinux users section.

The semanage login command updates the seusers file located inside /etc/selinux/targeted. If multiple group mappings are defined, then the order of mappings within this file defines which mapping applies to a given user. Users that belong to multiple mapped groups will be assigned an SELinux user based on the first match.

While it is possible to update the order of the entries in the seusers file, this is not recommended. Every time semanage login modifies the seusers file, it will reorder the mappings. Instead, when a user belongs to multiple mapped groups, we advise you to create an individual (user-based) mapping. This is also shown whenever we create a group mapping for a group that contains users for which active mappings already exist:

# semanage login -a -s guest_u %nginx
libsemanage.add_user: User taylor is already mapped to group users, but also belongs to group nginx. Add an explicit mapping for this user to override group mappings.

The changes take effect when a new login occurs, so we should force a logout for these users. The following command kills all the processes of the lisa user, forcing a logout for that user:

# pkill -KILL -u lisa

Also, when we modify a user’s settings, we should also reset the contexts of that user’s home directory (while that user is not logged in). To accomplish this, use restorecon as follows:

# restorecon -RF /home/lisa

The -F option in the preceding command forces a reset, while -R does this recursively.


Running the restorecon -RF command will also reset file contexts that the user has manually set using tools such as chcon. We recommend defining SELinux user mappings up front, or recursively changing only the SELinux user of the files using chcon -R -u.

To remove a login mapping, use the -d (delete) option. Don’t forget to run the restorecon command afterward:

# semanage login -d lisa
# restorecon -RF /home/lisa

Don’t forget to force a user logout again if this user is active on the system.

Customizing logins for services

When login mappings are added using semanage login, they apply to all services. There is no option in semanage to allow customizing the mappings based on the service. However, that does not mean it is not possible.

The SELinux user space tools and libraries will consult the following two configuration files to know what the mappings are:

  • The /etc/selinux/targeted/seusers file contains the standard, service-agnostic mappings. This file is managed by semanage login and should not be updated through any other means.
  • The /etc/selinux/targeted/logins directory contains customized mappings, one file per Linux account. So, the custom mapping for the root user will be in /etc/selinux/targeted/logins/root.

Inside the files for customized mappings, administrators can define, per service, a different SELinux user to map to. The services are the Pluggable Authentication Modules (PAM) services through which a user can log in, and more information on this can be found in the SELinux and PAM section.

For instance, to have the root user – when logged in through SSH – be mapped to the user_u SELinux user rather than their default unconfined_u user, the root file would need to contain the following:


When querying the current mapping, semanage login will show this customization as follows:

# semanage login -l
Local customization in /etc/selinux/targeted/logins
root		user_u		s0		sshd

Of course, this customization does not need to be so drastic. It can also be used to limit the user’s default MLS/MCS range. For instance, to limit the categories to c0.c8 (rather than the default c0.c1023 range) you would use the following:


Such customizations allow us to flexibly change the access control policies based on the PAM service used.

Creating SELinux users

By default, only a small number of SELinux users are available for mapping to logins. If we want more control over the Linux accounts and their mappings, we need to create additional SELinux users.

First, list the currently known SELinux users using the semanage user -l command, as follows:

# semanage user -l
SELinux	Labeling	MLS/		MLS/
User		Prefix	MCS Level	MCS Range		SELinux Roles
guest_u	user		s0		s0			guest_r
root		user		s0		s0-s0:c0.c1023	staff_r ...
xguest_u	user		s0		s0			xguest_r

Next, create a new SELinux user with semanage user, using the -a (add) option. We need to give SELinux additional information about this SELinux user, such as the following:

  • The default sensitivity (using the -L option) for the SELinux user. This is the sensitivity that the user starts with.
  • The security clearance (using the -r option) applicable to the SELinux user. This range cannot be extended when defining login mappings. It is, however, possible to give a user a more limited range, as long as it is bounded by the current range.
  • The allowed role or roles (using the -R option) for the SELinux user.


The labeling prefix shown in the previous example is used to dynamically create SELinux policies with specific prefixes, such as <prefix>_home_t for user’s home files. Most distributions leave this to the default user setting, and changing it is done through the (undocumented) -P parameter to semanage user.

In the following example, we’re configuring the SELinux user finance_u:

# semanage user -a -L s0 -r "s0-s0:c0.c127" -R user_r finance_u

When the command creates the SELinux user, its information becomes part of the SELinux policy. From this point onward, administrators can map Linux accounts to this SELinux user.


SELinux roles are enabled through the SELinux user that a Linux account is mapped to. When an administrator wants to allow additional existing roles to a Linux account, the administrator either updates existing SELinux mappings to include the new role(s) or creates a new SELinux user that has access to the new role(s) and then maps this SELinux user to the Linux account.

Just like with login mappings, semanage user also accepts the -m option to modify an existing entry, or -d to delete one. For instance, the following command deletes the finance_u SELinux user:

# semanage user -d finance_u

Separate SELinux users enhance the audit information since SELinux users generally do not change during a user’s session, whereas the effective Linux user ID can. If the user creates files or other resources, these resources also inherit the SELinux user part in their security context.

Listing accessible domains

When creating SELinux users, one of the parameters that needs to be provided is the role or roles for an SELinux user. Most of the roles are self-explanatory: the dbadm_r role is for DBAs, whereas the webadm_r role is for web application infrastructure administrators. If a role is not clear, or an administrator is not certain which accesses are part of a given role, the administrator can still query the SELinux policy for more information.

As documented earlier, roles define which domains are accessible for the users associated with the role. We saw that seinfo can show us the available roles, but it can do more. It can list the domains accessible for a role as well, using the -x option:

# seinfo -r dbadm_r -x
Roles: 1
  role dbadm_r types { ... qmail_inject_t user_mail_t ... };

In this example, users running with the dbadm_r role as part of their security context will be able to transition to, for instance, the qmail_inject_t (the domain used to read email messages and pass those on to the qmail queue) and user_mail_t (the domain used for generic email-sending command-line applications) domains.

The information provided through the dominated roles is usually not of concern to the administrators. Role dominance, although supported in SELinux core, is not used by Linux distribution policies. It signifies the inheritance of (other) roles, but it will always just show the queried role.

Managing categories

Sensitivity labels and their associated categories are identified through numeric values, which is great for computers but not that obvious for users. Luckily, the SELinux utilities support translating the levels and categories to human-readable values, even though they are still stored as numbers. As a result, almost all tools that can show contexts will show them translated rather than presented as numerical values.

The translations are managed through the setrans.conf file, located in /etc/selinux/targeted. Inside this file, we can name specific values (for example, s0:c102) or ranges (such as s0-s0:c1.c127) with a string that is much easier for administrators to use. However, for translations to be performed, mcstransd – the MCS translation daemon – needs to be running.

Consider our example of the finance_u SELinux user who was allowed access to the c0.c127 category range. Two of the categories within that range are c102, which we will tag as Contracts, and c103, which we will tag as Salaries. The c1.c127 range will be labeled as FinanceData. The following diagram shows the relationship between these various categories:

selinux user

To accomplish this, the following should be placed in the setrans.conf file:



After editing the setrans.conf file, the mcstransd application needs to be restarted.

These translations are handled by the SELinux utilities, which connect to the mcstransd daemon through the .setrans-unix socket located in /var/run/setrans to query the setrans.conf file. If the daemon is not running or the communication with the daemon fails, the numeric sensitivity and category values are displayed.

For instance, with the daemon running, the output of id -Z is now as follows:

# id -Z

We can view the available sensitivities and their human-readable counterparts using the chcat tool. The following example displays the translations after adding the finance-related ones:

$ chcat -L
s0			SystemLow
s0-s0:c0.c1023	SystemLow-SystemHigh
s0:c0.c1023	SystemHigh
s0:c102		Contracts
s0:c103		Salaries
s0-s0:c1.c127	FinanceData

The same chcat utility can be used to assign categories to users. For instance, to grant the Salaries category to the lisa Linux user, we’d use the following command:

# chcat -l -- +Salaries lisa

The previous command grants the Salaries category (c103) to the Linux user lisa. The user mapping is immediately updated with this information. Again, we need to make sure that the lisa user is logged out for the changes to take effect.

With this, we end our article on managing SELinux users and logins. We’ve learned how to align users with SELinux users so that they log in to the system with the correct context. In the next section, we will look at the SELinux roles and how to apply those to SELinux users.

Related Articles

No Results Found

The page you requested could not be found. Try refining your search, or use the navigation above to locate the post.

Lorem ipsum dolor sit amet consectetur


Submit a Comment

Your email address will not be published. Required fields are marked *

4 + twelve =