> ## Documentation Index
> Fetch the complete documentation index at: https://notes.kodekloud.com/llms.txt
> Use this file to discover all available pages before exploring further.

# File Context

> Explains SELinux file contexts, how they control file access, commands to view and change contexts, and a demo fixing Apache access by relabeling files with semanage and restorecon.

Now that you understand SELinux enforcement modes, the next key concept is file context. File contexts are SELinux labels attached to files and directories that determine which processes can access them—think of them as departmental labels on folders in an office. Even if UNIX permissions permit access, SELinux can deny it if the file's context does not match the service trying to use it.

![A diagram titled "File Context" illustrating SELinux access controls. It shows an HR folder accessible by the HR department but denied to Finance, and a web server allowed to access files for the same service but denied for a different service.](https://mintcdn.com/kodekloud-c4ac6d9a/1sYC1Pc8WY3l0d7u/images/Prep-Course-Red-Hat-Certified-System-Administrator-RHCSA/SELinux/File-Context/selinux-file-context-hr-finance-web.jpg?fit=max\&auto=format\&n=1sYC1Pc8WY3l0d7u\&q=85\&s=04572c3eaac4cbe409ad4a6d1bbfd75d)

## Viewing file contexts

Use `ls -Z` to display SELinux contexts for files and directories:

```bash theme={null}
$ ls -Z /var/www/html
system_u:object_r:httpd_sys_content_t:s0 index.html
```

A file context has four colon-separated fields:

| Field | Meaning | Example |
| - | - | - |
| `user` | SELinux user identity for the object | `system_u` |
| `role` | SELinux role (files commonly use `object_r`) | `object_r` |
| `type` | Primary attribute used by SELinux policy to allow or deny access | `httpd_sys_content_t` |
| `level` | MLS/MCS level (most standard systems use `s0`) | `s0` |

Components summary:

```text theme={null}
user:role:type:level

User  - SELinux user identity
Role  - SELinux role used in access control
Type  - Primary field used for policy decisions
Level - For MLS/MCS (usually s0)
```

When a process requests access to an object, SELinux compares the process context to the object context and consults the loaded policy to allow or deny the action—`type` is the most important field for those decisions.

## Check and change SELinux mode

Quick commands to check SELinux status:

```bash theme={null}
# Show current enforcement mode
root@control:~# getenforce
Enforcing

# Detailed status
root@control:~# sestatus
SELinux status:                enabled
SELinuxfs mount:               /sys/fs/selinux
SELinux root directory:        /etc/selinux
Loaded policy name:            targeted
Current mode:                  enforcing
Mode from config file:         enforcing
Policy MLS status:             enabled
Policy deny_unknown status:    allowed
Memory protection checking:    actual (secure)
Max kernel policy version:     33
```

Temporarily toggle enforcement at runtime:

```bash theme={null}
# Set permissive mode (SELinux logs denials but does not enforce)
root@control:~# setenforce 0
root@control:~# getenforce
Permissive

# Return to enforcing mode
root@control:~# setenforce 1
root@control:~# getenforce
Enforcing
```

Persistently change the mode by editing `/etc/selinux/config`:

```ini theme={null}
# /etc/selinux/config
# SELINUX= can be: enforcing, permissive, disabled
SELINUX=enforcing
SELINUXTYPE=targeted
```

As an alternative to the config file, you can pass `selinux=0` as a kernel argument to disable SELinux at boot. Use `grubby` to add or remove that kernel argument:

```bash theme={null}
# Persistently disable SELinux at kernel level
root@control:~# grubby --update-kernel=ALL --args="selinux=0"

# Remove the kernel argument to re-enable SELinux at boot
root@control:~# grubby --update-kernel=ALL --remove-args="selinux=0"
```

## Demo: Apache blocked by wrong file context

This demo walks through a common scenario: Apache cannot serve files located in a non-standard directory because those files have the wrong SELinux file context.

1. Install Apache and create a custom document root:

```bash theme={null}
# Install Apache
root@control:~# dnf install -y httpd

# Create a custom directory for content
root@control:~# mkdir -p /webcontent/html

# Create a simple index.html
root@control:~# echo "Hello world" > /webcontent/html/index.html
```

2. Point Apache to the new document root (place these directives in the appropriate httpd configuration file):

```apacheconf theme={null}
# Example configuration changes
DocumentRoot "/webcontent/html"

<Directory "/webcontent">
    AllowOverride None
    Require all granted
</Directory>

<Directory "/webcontent/html">
    # Options and other directives as needed
</Directory>
```

3. Start Apache and test:

```bash theme={null}
# Start the service
root@control:~# systemctl start httpd
root@control:~# systemctl status httpd --no-pager
# (status output omitted for brevity)
```

4. Request the page — on an enforcing system you may get a 403 Forbidden even though UNIX permissions allow access:

```bash theme={null}
root@control:~# curl -i http://localhost/index.html
HTTP/1.1 403 Forbidden
...
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>403 Forbidden</title>
</head><body>
<h1>Forbidden</h1>
<p>You don't have permission to access this resource.</p>
</body></html>
```

Confirm UNIX permissions are correct:

```bash theme={null}
root@control:~# ls -l /webcontent/html/
total 4
-rw-r--r--. 1 root root 12 Apr 27 13:32 index.html
```

Switch to permissive to confirm SELinux is the cause:

```bash theme={null}
# Confirm SELinux enforcing
root@control:~# getenforce
Enforcing

# Temporarily allow access by setting permissive
root@control:~# setenforce 0
root@control:~# curl -i http://localhost/index.html
HTTP/1.1 200 OK
...
Hello world
```

This demonstrates that SELinux was blocking access due to file context.

## Inspecting contexts: standard vs custom paths

Typical contexts for standard Apache content:

```bash theme={null}
root@control:~# ls -Z /var/www
system_u:object_r:httpd_sys_script_exec_t:s0 cgi-bin
system_u:object_r:httpd_sys_content_t:s0 html
```

The custom directory still has an unconfined/default label:

```bash theme={null}
root@control:~# ls -Z /webcontent
unconfined_u:object_r:default_t:s0 html
```

## Fixing file contexts with semanage and restorecon

To let Apache serve content from a non-standard directory, add a persistent file-context rule with `semanage fcontext` and then relabel files with `restorecon`.

You can consult the `semanage fcontext` manual for pattern examples; they help construct correct regular-expression paths for matching files and directories.

Example:

```bash theme={null}
# Add a file context rule to label /webcontent and everything under it as web content
root@control:~# semanage fcontext -a -t httpd_sys_content_t "/webcontent(/.*)?"

# Apply the labels to files and directories under /webcontent
root@control:~# restorecon -Rv /webcontent
Relabeled /webcontent from unconfined_u:object_r:default_t:s0 to unconfined_u:object_r:httpd_sys_content_t:s0
Relabeled /webcontent/html from unconfined_u:object_r:default_t:s0 to unconfined_u:object_r:httpd_sys_content_t:s0
Relabeled /webcontent/html/index.html from unconfined_u:object_r:default_t:s0 to unconfined_u:object_r:httpd_sys_content_t:s0
```

Verify the new context:

```bash theme={null}
root@control:~# ls -Z /webcontent
unconfined_u:object_r:httpd_sys_content_t:s0 html
```

Return to enforcing mode and retest:

```bash theme={null}
# Back to enforcing
root@control:~# setenforce 1

# Test the page
root@control:~# curl -i http://localhost/index.html
HTTP/1.1 200 OK
...
Hello world
```

Because the file type is now `httpd_sys_content_t`, the httpd policy permits Apache to serve files from `/webcontent/html`.

## Useful commands reference

| Command | Purpose |
| -: | - |
| `ls -Z <path>` | Show SELinux contexts for files and directories |
| `getenforce` | Show current SELinux enforcement mode |
| `sestatus` | Show detailed SELinux status and policy info |
| `setenforce 0\|1` | Temporarily set permissive (0) or enforcing (1) mode |
| `semanage fcontext -a -t <type> "<path_regex>"` | Add a persistent file-context rule |
| `restorecon -Rv <path>` | Apply/restore SELinux labels to files and directories |
| `grubby --update-kernel=ALL --args="selinux=0"` | Add kernel arg to disable SELinux at boot |
| `grubby --update-kernel=ALL --remove-args="selinux=0"` | Remove kernel arg to re-enable SELinux at boot |

## Summary

* SELinux file contexts are labels in the format `user:role:type:level`.
* The `type` field is used by policy to allow or deny accesses (e.g., `httpd_sys_content_t` for web content).
* Use `ls -Z` to inspect contexts; `semanage fcontext` and `restorecon` add and apply persistent labels.
* Toggle enforcement temporarily with `setenforce` or persistently via `/etc/selinux/config` or kernel arguments.
* When a service is denied access despite correct UNIX permissions, check SELinux contexts and policy.

## Links and references

* [SELinux Project Wiki](https://selinuxproject.org/page/Main_Page)
* [Red Hat SELinux Guide](https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/)
* `man semanage_fcontext` and `man restorecon` (local man pages)
* [Apache HTTP Server](https://httpd.apache.org/)

> **[Watch Video](https://learn.kodekloud.com/user/courses/red-hat-certified-system-administrator-rhcsa/module/b5144a7b-6b93-4267-853e-415af567e6d7/lesson/733eeb20-8d26-429d-90f3-66278a881b90)**


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.