SELinux

SELinux stands for Security-Enhanced Linux.

It is a Linux security system that adds an extra layer of access control on top of normal Linux file permissions.

Traditional Linux permissions are based on users, groups, and file modes such as:

SELinux goes further. It controls what processes are allowed to do, even if normal Linux permissions would allow the action.

The main idea is:

Normal permissions ask:
Does this user have access?

SELinux asks:
Is this process type allowed to access this object type?

SELinux is especially useful on servers because it limits damage if a service is compromised.

For example, if a web server is hacked, SELinux can prevent the web server process from reading private user files, modifying system files, or accessing resources outside its allowed policy.

DAC vs MAC

Linux normally uses Discretionary Access Control, or DAC.

SELinux adds Mandatory Access Control, or MAC.

With DAC, a user who owns a file can usually decide who can read or write it.

With MAC, the system policy can still block access, even if the file owner gives permission.

Example:

This is one of the most important SELinux concepts.

SELinux does not replace normal permissions. Both must allow the action.

Access allowed only if:

DAC allows it
AND
SELinux allows it

Big Picture

SELinux labels processes and resources.

These labels are called security contexts.

When a process tries to access a file, socket, port, or other object, SELinux compares the process context with the object context and checks the loaded policy.

+-------------------+
| Process           |
| Example: httpd    |
| Context: httpd_t  |
+---------+---------+
          |
          | wants to read
          v
+-------------------+
| File              |
| /var/www/html     |
| Context:          |
| httpd_sys_content_t
+---------+---------+
          |
          v
+-------------------+
| SELinux Policy    |
| Is httpd_t allowed|
| to read           |
| httpd_sys_content_t?
+---------+---------+
          |
          v
+-------------------+
| Allow or Deny     |
+-------------------+

The key decision is usually based on the type.

For processes, the type is often called a domain.

For files and other objects, the type is usually just called a type.

SELinux policy defines what domains can do to what types.

SELinux Architecture

A simplified SELinux architecture looks like this:

+---------------------------------------------------+
|                   User Process                    |
|        Example: web server, SSH daemon, app       |
+----------------------+----------------------------+
                       |
                       | 1. Access request
                       |    read, write, execute,
                       |    bind port, connect socket
                       v
+---------------------------------------------------+
|             SELinux Security Server               |
|             Policy Decision Point                 |
|                                                   |
| Checks loaded policy and security contexts        |
+----------------------+----------------------------+
                       |
                       | 2. Allow or deny decision
                       v
+---------------------------------------------------+
|       Object Manager and Access Vector Cache      |
|       Policy Enforcement Point                    |
|                                                   |
| Enforces decision and caches previous results     |
+----------------------+----------------------------+
                       |
                       | 3. Operation allowed or blocked
                       v
+---------------------------------------------------+
|                  Linux Kernel                     |
+---------------------------------------------------+

The important parts are:

Component Description
Subject The process trying to perform an action.
Object The resource being accessed.
Policy The SELinux rules that define permitted actions.
Decision The result of policy evaluation: allow or deny.
AVC (Access Vector Cache) Caches SELinux access decisions and records access denials for logging.

Subjects and Objects

A subject is usually a process.

Examples:

An object is something the process tries to access.

Examples:

Example:

Subject:
httpd process running as httpd_t

Object:
index.html labeled httpd_sys_content_t

Action:
read

SELinux checks whether httpd_t is allowed to read httpd_sys_content_t.

SELinux Contexts

Every SELinux-labeled process and object has a security context.

A context usually has four parts:

SELinux user : role : type : level

Example file context:

system_u:object_r:httpd_sys_content_t:s0

Breakdown:

Component Description
system_u SELinux user
object_r SELinux role for objects
httpd_sys_content_t SELinux type (domain/type label)
s0 Sensitivity level (MLS/MCS security level)

The type is usually the most important part for everyday troubleshooting.

In most common SELinux troubleshooting:
focus on the type.

Process Context Example

To view process contexts:

ps -eZ | grep sshd

Example output:

system_u:system_r:sshd_t:s0-s0:c0.c1023  1234 ? 00:00:00 sshd

Interpretation:

File Context Example

To view file contexts:

ls -Z /var/www/html/index.html

Example output:

-rw-r--r--. root root system_u:object_r:httpd_sys_content_t:s0 /var/www/html/index.html

Interpretation:

Why Labels Matter

SELinux does not only care about file paths.

It cares strongly about labels.

For example, two files may have the same normal permissions:

-rw-r--r-- index.html
-rw-r--r-- secret.txt

But they may have different SELinux types:

index.html   httpd_sys_content_t
secret.txt   user_home_t

A web server may be allowed to read httpd_sys_content_t but denied access to user_home_t.

This means a file can be readable by Unix permissions but still blocked by SELinux.

SELinux Modes

SELinux has three major modes:

Enforcing Mode

In enforcing mode, SELinux policy is active.

Unauthorized actions are blocked and logged.

SELinux policy says deny
        |
        v
Action is blocked
        |
        v
Denial is logged

This is the normal recommended mode for production systems.

Permissive Mode

In permissive mode, SELinux does not block actions, but it still logs what would have been denied.

SELinux policy says deny
        |
        v
Action is allowed anyway
        |
        v
Denial is logged

Permissive mode is useful for troubleshooting because it lets you see SELinux problems without breaking the application.

It should usually be temporary.

Disabled Mode

In disabled mode, SELinux is turned off.

No SELinux policy is enforced, and SELinux denials are not logged.

This is usually not recommended.

A key difference:

Switching from disabled back to enabled may require relabeling the filesystem.

Checking SELinux Mode

Use:

getenforce

Example outputs:

Enforcing

or:

Permissive

or:

Disabled

For more detail:

sestatus

Example output:

SELinux status:                 enabled
Current mode:                   enforcing
Mode from config file:          enforcing
Policy name:                    targeted

Interpretation:

Temporarily Changing SELinux Mode

To switch to permissive mode temporarily:

sudo setenforce 0

or:

sudo setenforce Permissive

To switch back to enforcing:

sudo setenforce 1

or:

sudo setenforce Enforcing

Verify:

getenforce

Important:

Permanently Changing SELinux Mode

The main configuration file is:

/etc/selinux/config

Open it:

sudo nano /etc/selinux/config

Example:

SELINUX=enforcing
SELINUXTYPE=targeted

Possible SELINUX values:

A reboot is usually required for this file to fully take effect.

Use caution before setting SELinux to disabled.

SELinux Policy Types

SELinux policy defines the rules.

Common policy types include:

For most systems, the common policy is:

targeted

Targeted Policy

Targeted policy confines selected services while allowing many normal user processes to run unconfined.

This is the default on many SELinux-enabled distributions.

Examples of commonly confined services:

Targeted policy is a good balance between security and usability.

Strict Policy

Strict policy applies SELinux controls much more broadly.

It can provide stronger confinement but requires much more planning and administration.

It is more likely to break normal workflows if not carefully configured.

For most learners and administrators, targeted policy is the practical starting point.

Common SELinux Tools

Useful commands include:

Some commands may require packages such as:

Package names vary by distribution.

Viewing Contexts

View file context:

ls -Z /path/to/file

View directory context:

ls -Zd /path/to/directory

Example:

ls -Zd /var/www/html

Output:

drwxr-xr-x. root root system_u:object_r:httpd_sys_content_t:s0 /var/www/html

View process context:

ps -eZ | grep httpd

or:

ps -eZ | grep nginx

Example:

system_u:system_r:httpd_t:s0  2345 ? 00:00:00 nginx

Interpretation:

The web service process is running in the httpd_t domain.

Some systems label Apache and Nginx web server processes using the same SELinux domain family, such as httpd_t.

Always check your actual system with ps -eZ.

Changing Contexts with chcon

The chcon command changes a file or directory context directly.

Example:

sudo chcon -t httpd_sys_content_t /srv/mywebsite/index.html

This changes only the type.

To apply recursively:

sudo chcon -R -t httpd_sys_content_t /srv/mywebsite

Important:

Use chcon for quick tests, not usually for permanent configuration.

Restoring Default Contexts with restorecon

The restorecon command restores files to their expected default SELinux context based on policy rules.

Example:

sudo restorecon -Rv /var/www/html

Options:

Example output:

Relabeled /var/www/html/index.html from unconfined_u:object_r:default_t:s0 to system_u:object_r:httpd_sys_content_t:s0

Interpretation:

Persistent Context Rules with semanage fcontext

For custom directories, use semanage fcontext.

Example:

sudo semanage fcontext -a -t httpd_sys_content_t "/srv/mywebsite(/.*)?"

Then apply it:

sudo restorecon -Rv /srv/mywebsite

This is the correct persistent approach for custom paths.

chcon vs semanage fcontext

chcon: - quick manual label change - useful for testing - not persistent against relabeling

semanage fcontext: - persistent label rule - survives restorecon - best for permanent custom paths

A good rule:

SELinux Booleans

SELinux booleans are policy switches.

They let administrators adjust policy behavior without writing a new policy module.

List all booleans:

getsebool -a

Filter for web server booleans:

getsebool -a | grep httpd

Example output:

httpd_can_network_connect --> off
httpd_enable_homedirs --> off
httpd_read_user_content --> off

Interpretation:

Temporarily Changing a Boolean

Example:

sudo setsebool httpd_can_network_connect on

This applies until reboot.

Permanently Changing a Boolean

Use -P:

sudo setsebool -P httpd_can_network_connect on

The -P option makes it persistent.

Common booleans:

Only enable booleans that are actually needed.

SELinux Ports

SELinux can also control which services may bind to which network ports.

For example, a web server is normally allowed to bind to ports labeled as HTTP ports.

View HTTP port mappings:

sudo semanage port -l | grep http_port_t

Example output:

http_port_t    tcp    80, 81, 443, 488, 8008, 8009, 8443

Interpretation:

Add a custom HTTP port:

sudo semanage port -a -t http_port_t -p tcp 8081

If the port already exists under another type, modify instead:

sudo semanage port -m -t http_port_t -p tcp 8081

Audit Logs and AVC Denials

SELinux denials are usually logged as AVC messages.

AVC means Access Vector Cache.

Main log location:

/var/log/audit/audit.log

Search for SELinux denials from today:

sudo ausearch -m avc -ts today

Search by command name:

sudo ausearch -m avc -c nginx

or:

sudo ausearch -m avc -c httpd

Example AVC denial:

type=AVC msg=audit(1609459200.123:456): avc:  denied  { read } for  pid=1234 comm="nginx" name="index.html" dev="sda1" ino=56789 scontext=system_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:default_t:s0 tclass=file

Breakdown:

Interpretation:

Explaining Denials with audit2why

Use:

sudo ausearch -m avc -ts today | audit2why

Example output:

type=AVC ... denied { read } ...
Was caused by:
Missing type enforcement rule.

Interpretation:

Using sealert

If setroubleshoot is installed:

sudo sealert -a /var/log/audit/audit.log

sealert can provide human-readable explanations and suggested fixes.

Use it as guidance, but do not blindly apply every suggestion.

Custom Policies with audit2allow

As a last resort, you can generate a custom policy module from audit logs.

Example:

sudo grep nginx /var/log/audit/audit.log | audit2allow -M nginx_custom
sudo semodule -i nginx_custom.pp

Important warning:

A custom policy should be reviewed carefully.

Standard SELinux Troubleshooting Workflow

When something fails and SELinux may be involved:

  1. Confirm the normal Linux permissions.
  2. Check SELinux mode.
  3. Check source process context.
  4. Check target file, directory, or port context.
  5. Search AVC denials.
  6. Interpret the denial.
  7. Fix the label, boolean, port type, or policy.
  8. Retest.
  9. Avoid disabling SELinux as the first fix.

Useful commands:

getenforce
sestatus
ls -Z path
ps -eZ | grep service
sudo ausearch -m avc -ts recent
sudo restorecon -Rv path
sudo semanage fcontext -a -t TYPE "PATH_REGEX"
sudo setsebool -P boolean_name on

Scenario 1: Check SELinux Mode and Temporarily Switch to Permissive

Learn how to check and temporarily change SELinux enforcement.

Check Mode

getenforce

Example output:

Enforcing

Simulate Troubleshooting Mode

sudo setenforce 0
getenforce

Example output:

Permissive

Interpretation:

Restore Enforcing Mode

sudo setenforce 1
getenforce

Expected output:

Enforcing

Important Lesson

Scenario 2: Simulate a Web Server File Context Problem

Show how a service can fail because files have the wrong SELinux label.

Situation

A web server is configured to serve files from:

/srv/mywebsite

The file permissions are correct, but the site returns:

403 Forbidden

or the service logs show access denied.

Simulate the Problem

Create test content:

sudo mkdir -p /srv/mywebsite
echo "Hello from SELinux test" | sudo tee /srv/mywebsite/index.html

Check context:

ls -Z /srv/mywebsite/index.html

Example output:

-rw-r--r--. root root unconfined_u:object_r:default_t:s0 /srv/mywebsite/index.html

Interpretation:

Check AVC Denial

sudo ausearch -m avc -ts recent -c nginx

or:

sudo ausearch -m avc -ts recent -c httpd

Example output:

type=AVC msg=audit(...): avc:  denied  { open } for  pid=1234 comm="nginx" path="/srv/mywebsite/index.html" scontext=system_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:default_t:s0 tclass=file

Interpretation:

Temporary Test Fix with chcon

sudo chcon -R -t httpd_sys_content_t /srv/mywebsite
ls -Z /srv/mywebsite/index.html

Expected context:

unconfined_u:object_r:httpd_sys_content_t:s0

Permanent Fix with semanage fcontext

sudo semanage fcontext -a -t httpd_sys_content_t "/srv/mywebsite(/.*)?"
sudo restorecon -Rv /srv/mywebsite

Example output:

Relabeled /srv/mywebsite/index.html from unconfined_u:object_r:default_t:s0 to system_u:object_r:httpd_sys_content_t:s0

Final Interpretation

Scenario 3: Demonstrate chcon Is Temporary

Show why chcon is not the best permanent fix.

Simulate

sudo chcon -R -t httpd_sys_content_t /srv/mywebsite
ls -Z /srv/mywebsite/index.html

Example output:

unconfined_u:object_r:httpd_sys_content_t:s0 index.html

Now run:

sudo restorecon -Rv /srv/mywebsite

If no persistent semanage fcontext rule exists, example output may show:

Relabeled /srv/mywebsite/index.html from unconfined_u:object_r:httpd_sys_content_t:s0 to unconfined_u:object_r:default_t:s0

Interpretation:

Permanent Fix

sudo semanage fcontext -a -t httpd_sys_content_t "/srv/mywebsite(/.*)?"
sudo restorecon -Rv /srv/mywebsite

Lesson

Scenario 4: Simulate a Web Server Network Connection Denied by Boolean

Show how SELinux booleans control optional service behavior.

Situation

A web application needs to connect from the web server to a backend service or database over the network.

The application fails even though networking and firewall rules are correct.

Check Boolean

getsebool httpd_can_network_connect

Example output:

httpd_can_network_connect --> off

Check AVC Denial

sudo ausearch -m avc -ts recent | grep name_connect

Example output:

avc:  denied  { name_connect } for  pid=2222 comm="nginx" dest=5432 scontext=system_u:system_r:httpd_t:s0 tcontext=system_u:object_r:postgresql_port_t:s0 tclass=tcp_socket

Interpretation:

Fix

Temporarily:

sudo setsebool httpd_can_network_connect on

Persistently:

sudo setsebool -P httpd_can_network_connect on

Verify:

getsebool httpd_can_network_connect

Expected output:

httpd_can_network_connect --> on

Lesson

Booleans are safer than custom policy when the policy already provides a supported switch.

Scenario 5: Simulate a Service Binding to a Nonstandard Port

Show how SELinux controls network port usage.

Situation

A web server is configured to listen on port:

8081

The service fails to start.

Check Logs

sudo ausearch -m avc -ts recent | grep name_bind

Example output:

avc: denied { name_bind } for pid=3333 comm="nginx" src=8081 scontext=system_u:system_r:httpd_t:s0 tcontext=system_u:object_r:unreserved_port_t:s0 tclass=tcp_socket

Interpretation:

The web server tried to bind to TCP port 8081.
SELinux does not currently label that port as an allowed HTTP port.

Check Allowed HTTP Ports

sudo semanage port -l | grep http_port_t

Example output:

http_port_t tcp 80, 81, 443, 488, 8008, 8009, 8443

Fix

Add port 8081 as an HTTP port:

sudo semanage port -a -t http_port_t -p tcp 8081

Verify:

sudo semanage port -l | grep http_port_t

Expected output includes:

8081

Restart service:

sudo systemctl restart nginx

or:

sudo systemctl restart httpd

Lesson

Scenario 6: Simulate FTP Access to Home Directories Blocked by SELinux

Show how booleans can allow or deny service access to user home directories.

Situation

FTP login works, but users cannot access files in their home directories.

Check Boolean

getsebool ftp_home_dir

Example output:

ftp_home_dir --> off

Check AVC Denial

sudo ausearch -m avc -ts recent -c vsftpd

Example output:

avc: denied { read } for pid=4444 comm="vsftpd" name="notes.txt" scontext=system_u:system_r:ftpd_t:s0 tcontext=unconfined_u:object_r:user_home_t:s0 tclass=file

Interpretation:

Fix

sudo setsebool -P ftp_home_dir on

Verify:

getsebool ftp_home_dir

Expected output:

ftp_home_dir --> on

Lesson

SELinux booleans allow common optional behaviors without writing custom policy.

Scenario 7: Simulate Permissive Mode Logging

Understand the difference between permissive and enforcing behavior.

Step 1: Put SELinux in Permissive Mode

sudo setenforce 0
getenforce

Expected output:

Permissive

Step 2: Trigger a Known SELinux Issue

For example, use a web content file with the wrong label:

sudo chcon -R -t default_t /srv/mywebsite

Access it through the web server.

Step 3: Check Logs

sudo ausearch -m avc -ts recent

Example output:

avc: denied { read } for pid=1234 comm="nginx" path="/srv/mywebsite/index.html" scontext=system_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:default_t:s0 tclass=file permissive=1

Interpretation:

Restore Enforcing Mode

sudo setenforce 1

Lesson

Scenario 8: Diagnose “Permission Denied” When Unix Permissions Look Correct

Show the standard SELinux troubleshooting pattern.

Situation

A service fails with:

Permission denied

But normal permissions look correct:

ls -l /srv/mywebsite/index.html

Example output:

-rw-r--r--. root root 25 Jun 1 12:00 /srv/mywebsite/index.html

Step 1: Check SELinux Mode

getenforce

Example:

Enforcing

Step 2: Check File Context

ls -Z /srv/mywebsite/index.html

Example:

unconfined_u:object_r:default_t:s0 index.html

Step 3: Check Process Context

ps -eZ | grep nginx

Example:

system_u:system_r:httpd_t:s0  1234 ? 00:00:00 nginx

Step 4: Check AVC Logs

sudo ausearch -m avc -ts recent -c nginx

Example:

avc: denied { read } for comm="nginx" scontext=system_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:default_t:s0 tclass=file

Interpretation:

Fix

sudo semanage fcontext -a -t httpd_sys_content_t "/srv/mywebsite(/.*)?"
sudo restorecon -Rv /srv/mywebsite

Scenario 9: Use audit2why Before Making Changes

Use audit tools to understand denials before fixing them.

Search and Explain

sudo ausearch -m avc -ts recent | audit2why

Example output:

type=AVC ... denied { read } ...
Was caused by:
Missing type enforcement rule.

Possible mismatch between source and target contexts.

Interpretation:

Good Fix Order

  1. Fix wrong labels.
  2. Enable correct booleans.
  3. Fix port labels.
  4. Only then consider custom policy.

Scenario 10: Generate a Custom Policy Only as a Last Resort

Understand how custom policy modules are created and why they require caution.

Simulate

Suppose a custom application myapp is denied access and there is no existing boolean or label fix.

Collect relevant denials:

sudo ausearch -m avc -ts recent -c myapp

Generate a policy module:

sudo ausearch -m avc -ts recent -c myapp | audit2allow -M myapp_local

This creates files such as:

Inspect the .te file before installing:

cat myapp_local.te

Example rule:

allow myapp_t var_log_t:file read;

Interpretation:

Install only after review:

sudo semodule -i myapp_local.pp

Lesson

Scenario 11: Full Troubleshooting Example for Custom Web Directory

Perform a complete SELinux troubleshooting workflow.

Symptom

A web server returns:

403 Forbidden

for content under:

/srv/mywebsite

Check Normal Permissions

ls -ld /srv/mywebsite
ls -l /srv/mywebsite/index.html

Example:

drwxr-xr-x. root root /srv/mywebsite
-rw-r--r--. root root index.html

Interpretation:

Check SELinux Mode

getenforce

Example:

Enforcing

Check Context

ls -Zd /srv/mywebsite
ls -Z /srv/mywebsite/index.html

Example:

unconfined_u:object_r:default_t:s0 /srv/mywebsite
unconfined_u:object_r:default_t:s0 /srv/mywebsite/index.html

Check Denials

sudo ausearch -m avc -ts recent -c nginx

Example:

avc: denied { getattr open read } for comm="nginx" path="/srv/mywebsite/index.html" scontext=system_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:default_t:s0 tclass=file

Interpret

Fix Permanently

sudo semanage fcontext -a -t httpd_sys_content_t "/srv/mywebsite(/.*)?"
sudo restorecon -Rv /srv/mywebsite

Verify

ls -Z /srv/mywebsite/index.html

Expected:

system_u:object_r:httpd_sys_content_t:s0 index.html

Retest

Restart or reload the web service if needed:

sudo systemctl reload nginx

or:

sudo systemctl reload httpd

Then test the page again.

Check for Remaining Denials

sudo ausearch -m avc -ts recent -c nginx

If no new denial appears, the SELinux labeling issue is resolved.

Scenario 12: Relabel a Filesystem After SELinux Was Disabled

Understand why relabeling may be needed after SELinux has been disabled.

Situation

SELinux was disabled for a while, then re-enabled. Some files may not have correct labels.

Safe Relabel Trigger

Create the autorelabel marker:

sudo touch /.autorelabel
sudo reboot

During boot, the system relabels files according to SELinux policy.

Interpretation:

Caution

Common SELinux Problems and Fixes

Problem: File Has Wrong Context

Symptoms:

Check:

ls -Z path
sudo ausearch -m avc -ts recent

Fix:

sudo restorecon -Rv path

or for custom paths:

sudo semanage fcontext -a -t correct_type "path_regex"
sudo restorecon -Rv path

Problem: Service Needs Optional Access

Symptoms:

Check booleans:

getsebool -a | grep service_name

Fix:

sudo setsebool -P boolean_name on

Problem: Service Uses Nonstandard Port

Symptoms:

Check:

sudo semanage port -l | grep service_port_type

Fix:

sudo semanage port -a -t correct_port_type -p tcp PORT

Problem: SELinux Denial but No Audit Logs

Possible causes:

Check:

getenforce
sudo systemctl status auditd
sudo journalctl -t setroubleshoot
sudo dmesg | grep -i avc

Problem: Someone Suggests “Just Disable SELinux”

Better approach:

Disabling SELinux removes a major security layer.

Useful Command Summary

Mode and status:

getenforce
sestatus
sudo setenforce 0
sudo setenforce 1

View contexts:

ls -Z file
ls -Zd directory
ps -eZ
ps -eZ | grep service

Fix file contexts:

sudo chcon -t TYPE file
sudo restorecon -Rv path
sudo semanage fcontext -a -t TYPE "path_regex"
sudo restorecon -Rv path

Booleans:

getsebool -a
getsebool -a | grep httpd
sudo setsebool boolean_name on
sudo setsebool -P boolean_name on

Ports:

sudo semanage port -l
sudo semanage port -l | grep http_port_t
sudo semanage port -a -t http_port_t -p tcp 8081
sudo semanage port -m -t http_port_t -p tcp 8081

Audit and troubleshooting:

sudo ausearch -m avc -ts today
sudo ausearch -m avc -ts recent
sudo ausearch -m avc -c nginx
sudo ausearch -m avc -ts recent | audit2why
sudo sealert -a /var/log/audit/audit.log

Custom policy:

sudo ausearch -m avc -ts recent -c myapp | audit2allow -M myapp_local
cat myapp_local.te
sudo semodule -i myapp_local.pp

Relabeling:

sudo touch /.autorelabel
sudo reboot

Safe Lab Rules

SELinux labs should be done carefully.

Practical Challenges

  1. Use getenforce and sestatus to check SELinux mode, policy type, and status.
  2. Use ls -Z and ps -eZ to compare file contexts and process contexts.
  3. Create a test directory under /srv/mywebsite, add an index.html file, and inspect its default SELinux context.
  4. Change a file context with chcon, then run restorecon and observe whether the context changes back.
  5. Add a persistent context rule with semanage fcontext, apply it with restorecon, and verify the result with ls -Z.
  6. Search for recent AVC denials with ausearch -m avc -ts recent.
  7. Use audit2why to explain an SELinux denial.
  8. List web-related booleans with getsebool -a | grep httpd, then explain what httpd_can_network_connect does.
  9. Add a custom HTTP port with semanage port, then verify it appears under http_port_t.
  10. Write a short troubleshooting report for one SELinux denial. Include the symptom, mode, process context, file or port context, AVC output, interpretation, and fix.