The Labeling System
SELinux (Security-Enhanced Linux) was originally developed by the NSA as a research project and later merged into the mainline Linux kernel in 2003. Red Hat adopted it as the default security module for RHEL, and it is the mandatory security framework on Android. Its design philosophy is: label everything, then write rules about which labels can interact.
Every kernel object in an SELinux system carries a security context (also called a label). This includes files, directories, network ports, processes, and even inter-process communication channels. You can inspect these labels by adding the -Z flag to standard commands — ls -Z for file labels, ps -eZ for process labels, id -Z for your own process's label.
A security context has four colon-separated fields:
user:role:type:level
system_u:system_r:httpd_t:s0
- user (
system_u): The SELinux user (distinct from the Unix user). Most processes aresystem_uorunconfined_u. - role (
system_r): Used in Role-Based Access Control (RBAC). Processes usesystem_rorobject_r. - type (
httpd_t): This is the field that matters most for day-to-day operations. Policy rules are almost entirely written in terms of types. - level (
s0): Used for Multi-Level Security (MLS/MCS).s0means "no special sensitivity level" — you can ignore this in most environments.
The SELinux policy is a compiled rulebook of type enforcement (TE) rules. Each rule follows the pattern:
allow <source_type> <target_type>:<object_class> { <permissions> };
For example:
allow httpd_t httpd_sys_content_t:file { read getattr open };
This rule says: "A process of type httpd_t (Apache) is allowed to read, getattr, and open files of type httpd_sys_content_t." If a file has any other type — say user_home_t or tmp_t — Apache cannot read it, even if the Unix permissions are 777.
This is why the mv vs cp distinction matters so much in SELinux environments. When you mv a file, the inode moves and its label travels with it. When you cp a file, a new inode is created in the destination directory and inherits the directory's default label. A file copied into /var/www/html/ gets httpd_sys_content_t automatically. A file moved there keeps whatever label it had at its origin.
A classic interview scenario: "An engineer copies a config file from /tmp to /var/www/html/ and Apache still can't read it, even though ls -la shows correct permissions. What's wrong?" The answer is the SELinux label. The file was created in /tmp and has type tmp_t. Apache's policy only allows reading httpd_sys_content_t. Fix: sudo restorecon -v /var/www/html/filename. This demonstrates you understand that "permission denied" has two possible causes in a MAC-enabled system.