How to Temporarily Set SELinux to Permissive Mode on Fedora

To temporarily set SELinux to permissive mode on Fedora, run `setenforce 0` as root, which allows the system to log violations without enforcing them until the next reboot.

You upgraded a service and it silently refuses to start

You rebooted after a routine dnf upgrade and your web server or database daemon will not launch. The service logs show a generic Permission denied or Cannot open shared object file message. You check the firewall rules. You verify the file ownership. You restart the network. Nothing changes. The real blocker is SELinux. You need to see exactly which policy rule is stopping the service, but you cannot afford to leave your system wide open while you figure it out. Switching to permissive mode temporarily gives you full visibility into the denials without breaking your running services.

What's actually happening

SELinux operates in three distinct states. Enforcing blocks unauthorized actions and logs them. Permissive allows all actions but logs the denials that would have occurred. Disabled turns off the SELinux kernel module entirely. Think of it like a security checkpoint at an airport. Enforcing means the guard checks every boarding pass and physically stops anyone without one. Permissive means the guard lets everyone through but writes down every name that fails the check. Disabled means the checkpoint is empty and no one is watching.

When you run setenforce 0, you are changing the kernel's runtime state. The change takes effect immediately across all processes. It does not touch the persistent configuration file. When the system reboots, the kernel reads /etc/selinux/config and returns to whatever mode was defined there. This separation between runtime and persistent state is intentional. It prevents a single typo or rushed debugging session from permanently weakening your security posture.

Permissive mode is a diagnostic window, not a security setting. It lets you observe what SELinux wants to block without actually blocking it. Once you identify the missing policy rule or the mislabeled file context, you fix the underlying issue and return to enforcing mode.

Reboot before you debug. Half the time the symptom is gone.

The fix

Check the current SELinux state before making changes. The getenforce command prints the active mode in plain text.

# Print the current runtime mode
getenforce

If the output reads Enforcing, switch to permissive mode. The setenforce command requires root privileges and communicates directly with the kernel security module.

# 0 tells the kernel to allow all actions but log denials
# This change is immediate and affects all running processes
sudo setenforce 0

The command returns instantly. There is no service restart required. SELinux does not run as a traditional systemd unit. It is a kernel subsystem. The mode switch propagates to every process that checks permissions after the command executes.

Convention aside: setenforce only changes the runtime state. If you edit /etc/selinux/config and change SELINUX=enforcing to SELINUX=permissive, you are altering the persistent boot configuration. Always prefer runtime switches for temporary debugging. Persistent changes survive reboots and can accidentally lock you out of security protections.

Run journalctl first. Read the actual error before guessing.

Verify it worked

Confirm the mode switch by querying the runtime state again.

# Verify the kernel is now in permissive mode
getenforce

The output should read Permissive. Trigger the failing service or application to generate a fresh denial. SELinux writes these events to the audit subsystem. You can read them directly from the journal or query the audit log.

# -t filters by the setroubleshoot tag
# -e jumps to the end of the journal
# This shows human-readable summaries of recent denials
journalctl -t setroubleshoot -e

The setroubleshoot package translates raw audit messages into plain English. It tells you which process was blocked, which file it tried to access, and which boolean or policy module you need to adjust. If you need the raw audit records for scripting or deeper analysis, use ausearch.

# -m avc filters for Access Vector Cache denials
# -ts recent limits output to the last few minutes
# This avoids scrolling through thousands of unrelated log lines
sudo ausearch -m avc -ts recent

The output contains lines starting with type=AVC. Each line includes the scontext (source process label), tcontext (target file or port label), and the denied permission. Copy the scontext and tcontext values. You will need them when you generate a custom policy module or fix a file label.

Snapshot the system before the upgrade. Future-you will thank it.

Common pitfalls and what the error looks like

The most common mistake is leaving the system in permissive mode after debugging. Permissive mode logs denials but does not enforce them. A compromised application can read or write files it should not touch. The system appears to work normally, but your security boundary is effectively gone. Always run sudo setenforce 1 immediately after you identify the root cause.

Another frequent issue is misreading the audit log. Raw ausearch output looks like this:

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

The scontext shows the process label (httpd_t). The tcontext shows the file label (user_home_t). The denied { read } field tells you the exact permission that was blocked. The permissive=1 flag at the end confirms the system allowed the action because it was in permissive mode. If you see permissive=0, the action was actually blocked.

If setenforce 0 fails with Cannot set SELinux mode: Permission denied, your kernel was likely compiled without SELinux support, or the selinuxfs filesystem is not mounted. This is rare on standard Fedora installations. Verify the mount point exists.

# Check if the SELinux filesystem is mounted
# It should appear at /sys/fs/selinux
mount | grep selinux

If the mount is missing, the selinux-policy package may be corrupted. Refresh your package metadata and reinstall the policy files.

# --refresh forces dnf to ignore cached metadata
# This ensures you pull the latest policy definitions
sudo dnf upgrade --refresh selinux-policy

Convention aside: dnf upgrade --refresh is the standard weekly maintenance command. It forces a metadata sync and applies available updates. Do not confuse it with dnf system-upgrade, which is reserved for crossing major Fedora releases. They handle completely different workflows.

If the boot menu is gone, GRUB rescue is your friend, not your enemy.

When to use this vs alternatives

Use permissive mode when you need to observe SELinux denials without interrupting running services. Use enforcing mode when your system is in production or when you have verified that all required policy modules are loaded. Use audit2allow when you need to generate a custom policy module from logged denials instead of relaxing security. Use restorecon when a file has the wrong label and you need to reset it to the default context defined in the policy. Stay on the default enforcing configuration if you only deviate from the baseline for brief debugging sessions.

Trust the package manager. Manual file edits drift, snapshots stay.

Where to go next