Mandatory access control (MAC) is a security model where access decisions are enforced by the operating system based on policies set by an administrator. Users and processes cannot override these policies, even if they own the resource in question. This is the fundamental difference between MAC and the discretionary access control (DAC) model that most people interact with daily.
If you have ever used chmod or chown on a Linux system, you have used DAC. The owner of a file decides who can read, write, or execute it. The problem is that the owner can also give away access to anyone - or accidentally grant it to everyone. Under mandatory access control, the system policy overrides the owner's preferences. Even root-owned processes can be restricted.
Under discretionary access control, every process runs with the full privileges of the user who started it. If you run a web browser as your user, that browser can read every file you own - your SSH keys, your email, your documents. There is nothing stopping it. The kernel checks ownership and permission bits, and if the user matches, access is granted.
This model breaks down in two scenarios:
Compromised applications. If an attacker exploits a vulnerability in your web browser, they inherit all of your permissions. They can read your SSH private keys, exfiltrate documents, or install a backdoor in your shell profile. DAC has no concept of "this process should only access its own files."
Malicious insiders. A user who owns a sensitive file can copy it, email it, or change its permissions to make it world-readable. DAC trusts the user to make correct access decisions. Mandatory access control does not.
MAC solves both problems by enforcing policy at the kernel level. A web server process labeled httpd_t can only access files labeled httpd_sys_content_t, regardless of Unix permissions. A user with a "Secret" clearance cannot copy a "Top Secret" document to an unclassified location, even if they have read access to it.
Mandatory access control did not appear out of nowhere. It is built on formal security models developed in the 1970s for military and government use.
Bell-LaPadula Model (1973). This model enforces confidentiality. It has two key rules: "no read up" (a subject cannot read data at a higher classification level) and "no write down" (a subject cannot write data to a lower classification level). This prevents information from flowing from high-security levels to low-security levels. A process with "Secret" clearance can read "Secret" and "Unclassified" data, but cannot write to "Unclassified" destinations. Bell-LaPadula is the theoretical foundation for MLS (Multi-Level Security) implementations in SELinux.
Biba Integrity Model (1977). Biba is the mirror image of Bell-LaPadula, but for integrity instead of confidentiality. Its rules are: "no read down" (do not read data from a lower integrity level) and "no write up" (do not write to a higher integrity level). This prevents untrusted data from corrupting trusted data. Windows Mandatory Integrity Control (used by Internet Explorer's Protected Mode) is based on Biba.
Type Enforcement (1980s-1990s). Instead of hierarchical clearance levels, type enforcement assigns a type label to every subject (process) and object (file, port, socket) in the system. The policy defines which type pairs are allowed to interact and what operations are permitted. This is the model SELinux uses. It is more flexible than Bell-LaPadula or Biba because the administrator defines arbitrary access rules rather than relying on a fixed hierarchy.
Linux has three major MAC implementations, all using the LSM (Linux Security Modules) framework:
SELinux. Developed by the NSA and first merged into the Linux kernel in 2003. SELinux uses type enforcement with security labels stored as extended attributes on every object in the system. The policy is compiled and loaded into the kernel at boot time. Every system call is checked against the policy before the kernel grants access. SELinux is the default MAC system on Red Hat Enterprise Linux, CentOS, Fedora, Rocky Linux, and AlmaLinux.
SELinux is the most powerful and the most complex. Its policy language supports type enforcement, role-based access control (RBAC), and multi-level security (MLS). A typical SELinux policy for a RHEL system contains tens of thousands of rules.
AppArmor. Developed by Immunix (later acquired by Novell, now maintained by Canonical). AppArmor uses path-based profiles instead of labels. Each confined application has a profile that lists the file paths it can access and the operations it can perform. AppArmor is the default MAC system on Ubuntu, SUSE Linux Enterprise, and Debian.
AppArmor is simpler to configure than SELinux. Profiles are human-readable text files, and tools like aa-genprof can generate profiles automatically by observing application behavior. The tradeoff is that path-based security has inherent weaknesses - hard links and bind mounts can potentially bypass path-based rules.
TOMOYO Linux. Developed by NTT Data Corporation and merged into the mainline kernel in 2009. TOMOYO uses pathname-based MAC like AppArmor but takes a different approach to policy generation. It emphasizes "learning mode" where the system observes normal operation and automatically builds a policy. TOMOYO is less widely deployed than SELinux or AppArmor but is notable for its approach to policy creation.
When you enable mandatory access control on a production Linux system, several things change:
Processes are confined. A web server can only access web content files, log files, and network ports that the policy allows. Even if an attacker achieves code execution inside the web server process, they cannot read /etc/shadow, access the database data directory, or bind to arbitrary ports.
Root is not omnipotent. Under DAC, root can do anything. Under MAC, root-owned processes are still subject to policy. The unconfined_t domain in SELinux is an exception (it has broad access), but services running in confined domains are restricted regardless of their Unix UID.
File labeling matters. In SELinux, creating a file in the wrong directory or moving a file to a new location can change its label and break access. The restorecon command fixes labels based on the policy's file context definitions. This is the most common source of confusion for SELinux newcomers - and why so many tutorials start with "set SELinux to permissive" (which you should not do in production).
Denials are logged. When MAC blocks an operation, it writes an audit log entry (an AVC denial in SELinux). These logs are your primary troubleshooting tool. The ausearch and audit2why tools translate raw denial messages into human-readable explanations and suggested fixes.
Mandatory access control is not just a compliance checkbox. It provides defense in depth against the most common attack patterns:
Web application compromise. An attacker exploits an RCE vulnerability in your web application. Without MAC, they have the full privileges of the web server user and can pivot to other services. With MAC, the web server process is confined to its policy - it cannot read SSH keys, access other services' data directories, or execute arbitrary binaries.
Container isolation. SELinux MCS (Multi-Category Security) labels assign unique categories to each container. Even containers running the same image with the same UID cannot access each other's files because their labels differ. This is stronger isolation than what Linux namespaces and cgroups alone provide.
Supply chain attacks. A compromised dependency runs malicious code inside your application. Under MAC, that code is still confined by the application's security policy. It cannot access resources outside the policy even though it runs within a trusted process.
Compliance requirements. PCI DSS, HIPAA, FedRAMP, and DISA STIGs all reference or require mandatory access control. SELinux in enforcing mode is specifically required by DISA STIGs for RHEL systems. Running without MAC in a regulated environment creates audit findings.
If you are on a RHEL-family system, SELinux is already running in enforcing mode. Do not disable it. Instead, learn to work with it:
If you are on Ubuntu, AppArmor is active by default. Check its status and review the profiles for your running services:
Mandatory access control is a skill you build over time. Start by understanding why denials happen. Use the audit logs. Resist the temptation to disable the entire system because one service is misbehaving. Fix the policy instead. That is the whole point - the system is telling you exactly what access is being requested and denied.
That is also what this game is for. Work through the levels to build hands-on experience with SELinux policy, and use the other guides as reference when you get stuck.