# Selinux ## Terminology Subjects vs Objects: - A Subject is a process (e.g., the Apache httpd process). - An Object is the thing a subject wants to access (e.g., a file, a directory, a network port, a system socket). Labels (Contexts): - Every single Subject and every single Object on an SELinux system has a label. This label is called an SELinux Context. - A process’s label is called a domain. - A file’s label is called a type. The Policy: - The SELinux policy is just a massive database of rules that says which domains can access which types. - A rule might say: “Allow the domain httpd_t (the Apache process) to read files with the type httpd_sys_content_t (web content).” Type Enforcement (TE): - This is the name of the engine that enforces these rules. When a Subject (process) tries to access an Object (file), the Linux kernel’s hook for SELinux checks their labels. - It looks up the rule in the policy. - If a rule allow httpd_t httpd_sys_content_t:file { read }; exists, the access is granted. - If no “allow” rule exists, the access is implicitly denied, and an event is logged to /var/log/audit/audit.log. An SELinux context is a string with four parts, separated by colons: `user:role:type:level` - User: An SELinux user (e.g., system_u, unconfined_u). This is not the same as your Linux user (root, john). It’s an identity within the policy. - Role: Used in Role-Based Access Control (RBAC). (e.g., system_r, object_r). - Level: Used in Multi-Level Security (MLS) and Multi-Category Security (MCS). (e.g., s0, or s0:c0,c1). This is what keeps containers (Docker, Podman) separate from each other. - For 99% of all system administration, you can COMPLETELY IGNORE the user, role, and level. The only part that matters for day-to-day troubleshooting is the third part: the type. This is the real label. - For a process (Subject), the type is its domain. - For a file (Object), the type is its type. ## Using Selinux ```bash # List labels # The type is the third item in the four colon-separated values ls -lZ /var ls -lZ /var/log ls -lZ . # List processes ps -eZ | grep -i auditd ps -eZ | grep -i clam ps -eZ | grep -i grep ``` ### Using Selinux Booleans When you see an "selinux denied" error you have two choices: 1. (Wrong) Write a custom policy module to allow this. 2. (Right) Check if there’s an “off” switch for this rule. This “off” switch is called an SELinux Boolean. Booleans are on/off toggles for common policy rules. They are the first thing you should check when you have a denial. Your workflow should look like: 1. Get a denial. 2. Run getsebool -a | grep service_name. 3. Read the list of booleans and find one that sounds like the action being denied. 4. Temporarily flip it with setsebool. 5. Test. If it works, make it permanent with setsebool -P. ```bash # Get all booleans getsebool -a # Find one that's relevant getsebool -a | grep -i clam # Flip an sebool on temporarily setsebool httpd_can_network_connect_db on # Flip sebool on permanently setsebool -P httpd_can_network_connect_db on ``` ### Using Selinux with Audit Log If the selinux boolean approach doesn't work. ```bash # Make sure you have the troubleshooting package installed sudo dnf install -y setroubleshoot-server # List all alerts sudo sealert -a /var/log/audit/audit.log # If sealert doesn't have a recommendation, like restorecon, then use audit2why # This will tell you what you should do to fix the issue sudo grep "denied" /var/log/audit/audit.log | tail -n 1 | audit2why # Check what rule would be created sudo grep "antivirus_t" /var/log/audit/audit.log | audit2allow -m clamav-notifysend # Create the .te (human readable) policy, compile it (.pp), and load it into the kernel sudo grep "antivirus_t" /var/log/audit/audit.log | audit2allow -M clamav-notifysend # Apply the policy sudo semodule -X 300 -i clamav-notifysend.pp # List active policies sudo semodule -l # Remove an active policy sudo semodule -r clamav-notifysend ``` ### Showing Dontaudit Rules Selinux will hide denies that are explicitly prohibited through a rule. ```bash # Show dontaudit rules semodule -DB # Hide dontaudit rules semodule -B ``` ## Compiling Modules If you have a `te` file you can compile to a `pp` file with the following: ```bash # Compile to module source, then to policy package checkmodule -M -m -o sample.mod sample.te semodule_package -o sample.pp -m sample.mod ``` ## Cloning a Virtual Machine ```bash cd active/os_fedora/selinux_policies sudo ausearch -c 'rpc-virtstorage' --raw | audit2allow -M my-rpcvirtstorage sudo semodule -X 300 -i my-rpcvirtstorage.pp ```