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

# Demo Investigating SELinux Issues

> Walks through diagnosing and resolving SELinux denials blocking Apache from binding a custom port and accessing web files by adjusting port labels and file contexts.

In this walkthrough you'll learn how to identify and resolve SELinux denials by troubleshooting a real-world scenario: starting Apache (httpd) fails because SELinux policy prevents it from binding to a custom port and from reading web content. The steps cover:

* Reproducing the failure
* Inspecting system logs and AVC denials
* Allowing httpd to bind to a custom TCP port
* Fixing file context labels so httpd can read content
* Verifying the service and content are accessible

## 1. Attempt to start Apache

Reproduce the failure by starting httpd:

```bash theme={null}
root@control:~# systemctl start httpd
```

Check the unit status to see why it failed:

```bash theme={null}
root@control:~# systemctl status httpd
● httpd.service - The Apache HTTP Server
     Loaded: loaded (/usr/lib/systemd/system/httpd.service; disabled; preset: disabled)
    Active: failed (Result: exit-code) since Mon 2026-04-27 13:46:50 EEST; 36s ago
   Process: 7815 ExecStart=/usr/sbin/httpd $OPTIONS -DFOREGROUND (code=exited, status=1/FAILURE)
 Main PID: 7815 (code-exited, status=1/FAILURE)
    Status: "Reading configuration..."
      CPU: 37ms

Apr 27 13:46:50 control systemd[1]: Starting httpd.service - The Apache HTTP Server...
Apr 27 13:46:50 control httpd[7815]: (13)Permission denied: AH00072: make_sock: could not bind to address [::]:9495
Apr 27 13:46:50 control httpd[7815]: (13)Permission denied: AH00072: make_sock: could not bind to address 0.0.0.0:9495
Apr 27 13:46:50 control httpd[7815]: no listening sockets available, shutting down
Apr 27 13:46:50 control httpd[7815]: AH00015: Unable to open logs
Apr 27 13:46:50 control systemd[1]: httpd.service: Main process exited, code=exited, status=1/FAILURE
Apr 27 13:46:50 control systemd[1]: httpd.service: Failed with result 'exit-code'.
Apr 27 13:46:50 control systemd[1]: Failed to start httpd.service - The Apache HTTP Server.
```

The failure shows `Permission denied` when attempting to bind to port `9495` — this commonly indicates an SELinux denial on the network port.

## 2. Inspect SELinux-related messages

Check system logs for SELinux messages (on many distributions either `/var/log/messages` or `journalctl`):

```bash theme={null}
root@control:~# cat /var/log/messages | tail -n 30
```

The logs show setroubleshoot messages indicating SELinux prevented httpd from binding to TCP port `9495`. setroubleshoot suggests running `sealert` for the full report.

View the full sealert report (sample ID shown):

```bash theme={null}
root@control:~# sealert -l cbd2d8bb-9cd7-4ded-b0a9-6240d075fa67
SELinux is preventing /usr/sbin/httpd from name_bind access on the tcp_socket port 9495.

*****   Plugin bind_ports (92.2 confidence) suggests   *******************

If you want to allow /usr/sbin/httpd to bind to network port 9495
Then you need to modify the port type.
Do:
# semanage port -a -t PORT_TYPE -p tcp 9495
where PORT_TYPE could be: http_port_t, http_cache_port_t, ...

*****   Plugin catchall_boolean (7.83 confidence) suggests   ****************

If you want to allow nis to be enabled
Then you must tell SELinux about this by enabling the 'nis_enabled' boolean.

Do:
*****   Plugin catchall (1.41 confidence) suggests   ******************

If you believe that httpd should be allowed name_bind access on the port 9495 by default,
then you should report this as a bug. You can generate a local policy module to allow this access:
# ausearch -c 'httpd' --raw | audit2allow -M my-httpd
# semodule -i my-httpd.pp
```

Alternatively, search for AVC denials directly with `ausearch`:

```bash theme={null}
root@control:~# ausearch -m AVC
```

This confirms that httpd was denied `name_bind` for `tcp` port `9495`.

## 3. Check current SELinux port labels for httpd

List the SELinux port types and filter for http-related entries:

```bash theme={null}
root@control:~# semanage port -l | grep http
http_port_t                    tcp      80, 81, 443, 488, 800, 8080, 8443
http_cache_port_t              tcp      3128, 8088
```

Here you can see `9495` is not listed under `http_port_t`. SELinux will block httpd from binding to ports that are not labeled for the service by default.

## 4. Allow httpd to bind to port 9495

Add a port mapping so SELinux permits httpd to bind to your chosen port. Use the type appropriate for your use case; `http_port_t` is the common choice for general web server ports:

```bash theme={null}
root@control:~# semanage port -a -t http_port_t -p tcp 9495
```

If `semanage` reports the mapping already exists, modify the existing mapping:

```bash theme={null}
root@control:~# semanage port -m -t http_port_t -p tcp 9495
```

Verify the change:

```bash theme={null}
root@control:~# semanage port -l | grep 9495
http_port_t                    tcp      9495
```

Start httpd again and check status:

```bash theme={null}
root@control:~# systemctl start httpd
root@control:~# systemctl status httpd --no-pager
● httpd.service - The Apache HTTP Server
     Loaded: loaded (/usr/lib/systemd/system/httpd.service; disabled; preset: disabled)
    Active: active (running) since Mon 2026-04-27 13:55:10 EEST; 5s ago
```

At this point the service runs, but attempting to fetch the site returns a `403 Forbidden`. That indicates a separate SELinux denial — typically a file-label (context) issue preventing httpd from reading the files.

## 5. Verify HTTP access and file context

Attempt to fetch the index page:

```bash theme={null}
root@control:~# curl -sS localhost:9495/index.html -D - -o /dev/null
HTTP/1.1 403 Forbidden
```

Inspect the SELinux file context on the web content directory (example path `/webcontent/html` used here):

```bash theme={null}
root@control:~# ls -ldZ /webcontent /webcontent/html
drwxr-xr-x. root root system_u:object_r:default_t:s0 /webcontent
drwxr-xr-x. root root system_u:object_r:default_t:s0 /webcontent/html
```

These entries are labeled `default_t` instead of the expected `httpd_sys_content_t`. That mismatch prevents httpd from reading the files under the default SELinux policy.

Check the logs for related AVC denials:

```bash theme={null}
root@control:~# cat /var/log/messages | tail -n 30
Apr 27 13:53:47 control setroubleshoot[8228]: SELinux is preventing /usr/sbin/httpd from getattr access on the file /webcontent/html/index.html. For complete SELinux messages run: sealert -l 3d587974-213b-4768-a901-d201c5f1399e
```

You can also query AVC denials and suggest allow rules:

```bash theme={null}
root@control:~# ausearch -m AVC | audit2allow
```

## 6. Relabel files so httpd can read them

To allow httpd to serve files from `/webcontent`, add a file-context rule mapping that path to `httpd_sys_content_t` and then apply the labels.

1. Add the file-context rule (recursive pattern):

```bash theme={null}
root@control:~# semanage fcontext -a -t httpd_sys_content_t '/webcontent(/.*)?'
```

2. Apply the new labels with `restorecon`:

```bash theme={null}
root@control:~# restorecon -R -v /webcontent
```

Verify the updated labels:

```bash theme={null}
root@control:~# ls -ldZ /webcontent /webcontent/html /webcontent/html/index.html
drwxr-xr-x. root root system_u:object_r:httpd_sys_content_t:s0 /webcontent
drwxr-xr-x. root root system_u:object_r:httpd_sys_content_t:s0 /webcontent/html
-rw-r--r--. root root system_u:object_r:httpd_sys_content_t:s0 /webcontent/html/index.html
```

Re-test access:

```bash theme={null}
root@control:~# curl -sS localhost:9495/index.html
<!DOCTYPE html>
<html>
  <head><title>Index</title></head>
  <body><h1>Welcome</h1></body>
</html>
```

The page is now served correctly.

## Quick reference — useful commands

| Purpose | Command / Example |
| - | - |
| Check SELinux mode | `getenforce` |
| Start / status unit | `systemctl start httpd` / `systemctl status httpd --no-pager` |
| Search AVC denials | `ausearch -m AVC` |
| View sealert report | `sealert -l <ID>` |
| List SELinux ports | `semanage port -l` |
| Add port mapping | `semanage port -a -t http_port_t -p tcp 9495` |
| Modify port mapping | `semanage port -m -t http_port_t -p tcp 9495` |
| Add file-context rule | `semanage fcontext -a -t httpd_sys_content_t '/webcontent(/.*)?'` |
| Apply file contexts | `restorecon -R -v /webcontent` |
| Generate local allow module | `ausearch -c 'httpd' --raw \| audit2allow -M my-httpd` then `semodule -i my-httpd.pp` |

<Callout icon="lightbulb" color="#1CB2FE">
  On some systems the `semanage` command is provided by the `policycoreutils-python-utils` or `policycoreutils-python` package. Install it with your distribution package manager if `semanage` is not present (for example: `dnf install -y policycoreutils-python-utils` or `yum install -y policycoreutils-python`).
</Callout>

<Callout icon="warning" color="#FF6B6B">
  Be cautious when opening ports or changing file contexts. Only allow ports and contexts that are necessary for your service. If you are unsure, generate an SELinux policy module using `audit2allow` and review it before installing with `semodule -i`.
</Callout>

## Recap and troubleshooting checklist

* Use `getenforce` to confirm SELinux mode (Enforcing vs Permissive).
* For port bind failures:
  * Inspect `systemctl status` and logs.
  * Use `ausearch -m AVC` and `sealert` for detailed SELinux denial messages.
  * Use `semanage port -l` to find the correct SELinux port type and add the port with `semanage port -a -t <type> -p tcp <port>`.
* For file-access (403) errors:
  * Check file contexts with `ls -Z`.
  * Add a file-context rule with `semanage fcontext` and apply it with `restorecon -R`.
* For creating temporary or permanent policy exceptions:
  * Collect the denial with `ausearch` and feed to `audit2allow` to create a local module (`-M`) and install it with `semodule -i`.
* Always verify changes by restarting the service and testing access.

## Links and references

* SELinux project: [https://selinuxproject.org/](https://selinuxproject.org/)
* Red Hat SELinux guide: [https://access.redhat.com/documentation/en-us/red\_hat\_enterprise\_linux/](https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/)
* semanage man page: `man semanage`
* audit2allow and ausearch: [https://linux.die.net/man/8/audit2allow](https://linux.die.net/man/8/audit2allow)

Following these steps allows you to diagnose SELinux denials, permit necessary actions safely, and restore correct file and port contexts while keeping SELinux enforcement intact.

<CardGroup>
  <Card title="Watch Video" icon="video" cta="Learn more" href="https://learn.kodekloud.com/user/courses/red-hat-certified-system-administrator-rhcsa/module/b5144a7b-6b93-4267-853e-415af567e6d7/lesson/30e1af3d-4835-4c0a-9799-07c323ef6da8" />

  <Card title="Practice Lab" icon="flask-conical" cta="Learn more" href="https://learn.kodekloud.com/user/courses/red-hat-certified-system-administrator-rhcsa/module/b5144a7b-6b93-4267-853e-415af567e6d7/lesson/2cfe9a68-8d08-48fc-b66e-939cb51eae5f" />
</CardGroup>


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