# Selinux

<https://thecybersecguru.com/tutorials/selinux-ultimate-guide/>

## 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
```
