Understanding the identity layer in SELinux: the difference between Linux users and SELinux users, login mapping with semanage login, the concept of roles to restrict administrator domain transitions, and the MLS and MCS mechanisms for hierarchical data classification and workload isolation.

In episode 7, you resolved denials with local policy modules. But there's one thing we haven't touched: who runs that process. So far we've talked about domains — but domains are entered by humans through login sessions. This episode 8 discusses the SELinux identity layer: users, roles, and two classification mechanisms, MLS and MCS.
This is also the episode where SELinux concepts start to feel "different" from regular Linux. If you're used to thinking in UIDs and groups, get ready: SELinux has its own list of users, completely separate from Linux accounts.
Every process has two identities at once: a UNIX identity (UID, GID) governing traditional rights, and an SELinux security context. See your own login session's identity:
id -ZThe output for a regular user on the targeted policy is usually unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023. The first part, unconfined_u, is the SELinux user — not the Linux account. A Linux user is mapped to one SELinux user, and this mapping determines the initial domain of all the processes they run.
Note
The analogy: a Linux account is the ID card at the building gate, while the SELinux user is the badge that determines which floors you're allowed to enter. Two different ID cards (alice and bob) can use the same badge — or different badges — depending on administrator policy.
The list of built-in SELinux users is shown with semanage user -l:
| SELinux user | Initial domain | Usage |
|---|---|---|
unconfined_u | unconfined_t | unrestricted, for admins and development |
staff_u | staff_t | admin who can escalate to sysadm_t via role |
user_u | user_t | regular user with a locked domain |
guest_u | guest_t | highly restricted guest user |
xguest_u | xguest_t | guest user for desktop sessions |
system_u | system domain | for daemons and system processes, not humans |
Notice system_u: it's meant for system processes, not human logins. The default mapping used by all Linux users on the targeted policy is usually __default__ pointing to unconfined_u — this is why many admins feel "SELinux doesn't restrict anything" until they change this mapping.
The mapping between Linux users and SELinux users is managed with semanage login:
semanage login -lExample output:
Login Name SELinux User MLS/MCS Range Service
__default__ unconfined_u s0-s15:c0.c1023 *
root unconfined_u s0-s15:c0.c1023 *
alice user_u s0 *To map a Linux account to a more locked-down SELinux user:
sudo semanage login -a -s user_u aliceAfter this, all processes started by alice run in the user_t domain — far more tightly locked than unconfined_t. To apply it to all users except special ones, change __default__:
sudo semanage login -m -S targeted -s user_u __default__The consequences are significant: if an application needs full freedom, it must be moved to a dedicated service account with a staff_u or similar mapping. This is the trade-off that always accompanies user access hardening.
A role is the set of domains an SELinux user is allowed to enter. A user's login session starts in the domain corresponding to their primary role, for example user_t. For admins, SELinux provides a controlled role transition: newrole moves the session to a higher role with re-authentication:
newrole -r sysadm_rThis command requires your password again and puts your session in the sysadm_t domain — which has far greater administrative rights. Roles prevent silent escalation: even if a staff_u user is compromised, the attacker still has to go through newrole (with the victim's password) to gain admin rights.
The list of roles available to one SELinux user is managed with semanage user:
sudo semanage user -m -R "staff_r sysadm_r" staff_uThe right analogy: roles are the floors of a building, newrole is the elevator that requires the card again. The SELinux policy ensures processes can't just "ride the elevator up" without authorization.
MLS (Multi-Level Security) implements the Bell-LaPadula model: every subject and object has a sensitivity level, from s0 (lowest) to s15 (highest). The basic rules are simple:
s0 subject may not read s1 data.s1 subject may not write to an s0 object.Look at the level range of each SELinux user in the earlier semanage user -l output: s0-s15:c0.c1023 means the whole sensitivity range from s0 to s15 is allowed. This range is the user's clearance. On an MLS policy, a user with s0 clearance will never read an s1 document, even if type rules allow it.
MLS systems are rarely used outside government and military environments — that's where terms like top secret and secret become real levels in the policy. For most companies, the more relevant mechanism is MCS.
MCS (Multi-Category Security) shares the same infrastructure as MLS but uses categories instead of hierarchy. Categories are numbered c0 through c1023, and levels are written like this:
s0:c0.c1023 — all categories from c0 to c1023.s0:c1,c3 — only categories c1 and c3.Unlike MLS, which is hierarchical, MCS categories are not graded: c2 isn't "higher" than c1. They're just group labels for lateral isolation — separating one workload from another even though both run on the same host.
Categories are what let container runtimes separate processes: each container gets a unique category, for example s0:c123, so container A's processes can't read container B's files just because both share the same type. Set a directory's category range with chcon:
sudo chcon -r s0:c1 /srv/tenant-aTip
A way to remember the difference: MLS is a height hierarchy (can be read upward or downward), MCS is a separation between rooms (not interconnected). MLS is for high-assurance systems with hierarchical clearance, MCS for isolation between tenants and workloads — a pattern we'll see again in the container episode.
In this episode 8, you've understood that SELinux identity is layered in three parts: the SELinux user determines identity and level range, roles restrict which domains can be entered, and the MLS/MCS level determines what data can be read. You've also mapped Linux accounts to SELinux users with semanage login and raised privileges in a controlled way with newrole.
The key takeaways:
semanage login.newrole prevent unauthenticated privilege escalation.Now that identity is in order, it's time to use it on the most popular services in the world. In episode 9, we'll apply all these concepts to Web Server & Application Services: the correct file contexts for Nginx and Apache, booleans for network and database connections, port labeling with semanage port, and multi-instance patterns for MySQL and PostgreSQL.