This models Mandatory Access Control (MAC) as implemented by SELinux Type Enforcement (and, with a slightly different rule syntax, AppArmor profiles). Unlike discretionary access control (file owner decides), every subject (process) and every object (file/socket/resource) carries a fixed security type assigned by policy, not by the user:
decision(s, o, a) = ALLOW if (type(s), type(o), a) ∈ R
= DENY otherwise (default-deny)
Enforcing mode: DENY → access blocked, avc: denied {…} logged
Permissive mode: DENY → access still happens, avc: denied {…} logged only
R is the compiled policy ruleset: a small, explicit allow-list per domain (httpd_t may touch web_content_t and log_t; sshd_t may touch etc_t and log_t; and so on). Anything not explicitly listed is denied by default — the opposite of a blocklist firewall model.
- Policy strictness — a looser policy grants extra cross-domain rules (e.g. backup_t reading etc_t), trading isolation for convenience, exactly like tuning a real SELinux policy module.
- Inject compromised process — spawns a subject with no legitimate policy rules that repeatedly targets sensitive objects (shadow_t, etc_t), showing why MAC contains a compromised process even if it runs as root: root's Unix identity does not grant a policy-allowed type.
- Enforcing vs Permissive — Permissive is a real SELinux mode used to test a new policy: nothing is ever blocked, but every would-be denial is still written to the audit log, which is exactly why the log line is orange, not red, in that mode.
Real-world relevance: this is the actual decision function inside `security_compute_av()` in the Linux Security Module (LSM) hook path that SELinux and AppArmor both implement — every file open, socket bind and ptrace call on a hardened Linux box passes through a check shaped exactly like this.