

Starting in Red Hat Enterprise Linux 9, SELinux can be fully disabled only by using the selinux=0 kernel parameter at boot. RHEL no longer supports setting the SELINUX=disabled option in the /etc/selinux/config file.
If you want to disable it, check this out: https://access.redhat.com/solutions/3176
Starting in RHEL 9, disabling SELinux in the /etc/selinux/config file results in SELinux starting and performing active enforcement, but without loading any policies. Because policy rules define allowed actions, if no policies are loaded then all actions are denied. This behavior is intentional, and is designed to block malicious attempts to circumvent SELinux protection.
All resources, such as processes, files, and ports, are labeled with an SELinux context. SELinux maintains a file-based database of file labeling policies in the /etc/selinux/targeted/contexts/files/ directory.
When you copy a file, a new file is created with its own inode (a kind of "identity" for the file). The inode has various details, like its SELinux context, which need to be set up when the file is created. The copied file receives the default SELinux context based on the target directory's context type. If you want to preserve the context, you can do cp -a or cp --preserve=context source_file destination/
However, when you move a file within the same file system, it doesn't create a new inode. Instead, it just changes the file's location while keeping the same inode. Since the inode's details don’t need to be re-set, the file keeps its SELinux context when moved, unless you specifically change it using the -Z option.
SELinux tries to keep your system locked down in one of two ways: targeted mode or MLS mode.
By default, SELinux runs in targeted mode, which lets you decide what needs protection. It's a practical, “let's not go overboard” approach.
Then there’s MLS (Multi-Level Security). This mode is based on the Bell–LaPadula model, which was cooked up for the U.S. Department of Defense. It enforces layers of secrecy, ranging from c0 (meh, public info) to c3 (Top Secret, James Bond-level stuff). But here’s the kicker, the scale actually goes up to c1023. Nobody’s quite sure what to do with those extra levels yet, but hey, if you’re running a black ops mission from your home lab, this might be your thing. If you want to dive in, just install the selinux-policy-mls package.
Selinux state is either enabled or disabled. You must reboot to switch between the two. Enabled has two modes, permissive or enforcing.
If you want to temporarily disable SELinux to debug or analyze something you should change the SELinux state while booting by using a kernel parameter.
enforcing=0 will start SELinux in permissive mode.
enforcing=1 will start SELinux in enforcing mode.
selinux=0 will disable SELinux.
You can also just do setenforce 0 on the command line, then do getenforce to verify it's in a permissive state. That's a quick and easy way to confirm it's an SELinux issue or not.
SELinux decisions are stored in a special cache area called Access Vector Cache (AVC).
The Who, What, and How of Selinux Security
Everything in an SELinux-enabled system, files, processes, users, ports, has a security context. Think of it as a label that defines who it is, what role it plays, and what it’s allowed to do.
A security context looks like this:
system_u:object_r:httpd_sys_content_t:s0
Context labels have four components: user, role, type, and sensitivity level.
system_u → The SELinux user (not the same as a Linux user).
object_r → The role, (used mostly in MLS setups).
httpd_sys_content_t → The type, which is the most important part for access control.
s0 → The MLS/MCS level (if using Multi-Level Security).
Context Types: The Most Important Piece
Among all these fields, type is the one that really determines what can or can’t happen. SELinux policies are built around types, deciding which types can interact.
For example:
httpd_t → The type for the Apache process
httpd_sys_content_t → The type for web content
ssh_t → The type for SSH processes
If Apache (httpd_t) tries to read a file labeled httpd_sys_content_t, SELinux will check if that’s allowed. If it’s not, boom, denied.
Important commands:
View file contexts: ls -Z
View process contexts: ps -Z
View user contexts: id -Z
Manage contexts: semanage
By default, regular Linux users map to unconfined_u SELinux user (unrestricted), but confined SELinux users with limited privileges can be configured for better security.
CONTEXT
Remember to look at man semanage-fcontext during the exam. At the bottom you have examples you can use.
semanage fcontext -l
When files are created in a directory, they typically inherit the context of the parent directory and most services don't need additional SELinux configuration if default settings are used.
When files are copied, they typically inherit the context of the parent directory. If it's not relabeled correctly you can use restorecon -Rv /mydirectory.
Use semanage fcontext to set the file context label. This will write the context to the SELinux Policy, but it is not written yet to the filesystem. A second step is necessary to write it to the filesystem by using restorecon.
Instead of using restorecon you can use touch /.autorelabel to relabel all files to the context that is specified in the policy. That should be our last option, it happens while rebooting. So restorecon is preferred.
Use semanage fcontext -a to set a new context label. If you get an error that it already exists. Use semanage fcontext -m to modify an existing context label.
Important for the exam! See man semanage-fcontext for documentation.
If you apply non-default configuration, check the default configuration context setting but if that's not available install the man pages with dnf install selinux-policy-doc and then man -k selinux | grep http as an example.
Do NOT use chcon on the exam as the changes it makes will be overwritten.
Use semanage fcontext -I -C to show only settings that have changed in the current policy.
CONTEXT TYPES
Context labels have three components: user, role, and type
Type is most important for RHCSA - defines allowed operations on objects
View context labels with -Z option (e.g., ls -Z /etc/)
SELinux policy rules use these types to control access between source and target objects
BOOLEANS
Booleans in SELinux are like light switches for security settings—simple on/off toggles that let you enable or disable specific parts of the policy without rewriting everything from scratch.
Want a list of all available booleans? Run: semanage boolean -l or getsebool -a.
Need to see only the ones that aren’t set to their defaults? Try: semanage boolean -l -C
Curious about FTP-related settings? Pipe it through grep: getsebool -a | grep ftp
To flip a boolean, use: setsebool -P boolean_name on|off
That -P flag is crucial—without it, your changes will vanish the next time you reboot. (And trust me, realizing that after a restart is the kind of frustration that makes people disable SELinux entirely. Don’t be that person.)
So, if you need to tweak SELinux behavior, booleans are your friend. They’re quick, effective, and don’t require diving into the depths of policy files. Just flip the right switches and carry on.
NETWORKING
Network ports are also provided with an SELinux context label. The SELinux policy is configured to allow default port access. For any non-default port access, use semanage-port to apply the right label to the port.
Use the examples section in man semanage-port for examples.
Great hint for the exam!
semanage port -l
semanage port -a -t http_port_t -p tcp 81
COMMANDS
sestatus to see the status of SELinux
getenforce to see just the status of enforcing.
setenforce to switch between modes, permissive or enforcing. This is temporary, it will go back to whatever is defined in "/etc/selinux/config" after the server is rebooted.
ps Zaux to see relevant SELinux information regarding processes.
These commands are available through multiple packages, such as libselinux-utils provides getenforce, getenforce, and getsebool commands, policycoreutils contains sestatus, setsebool, and restorecon commands, policycoreutils-python-utils provides the semanage command, and setools-console includes the seinfo and sesearch commands.
USER MANAGEMENT
Not necessary for the RHCSA exam but good to know. When a user role is changed, it doesn’t take effect until the next login. SELinux users are part of the SELinux policy and are mapped to Linux users via configuration files. /etc/selinux/targeted/contexts/users
semanage login -a -s user_u armann
seinfo -u
semanage login -l
User Context | Features |
guest_u | No GUI, no networking, no access to the su or sudo command, no file execution in /home or /tmp |
xguest_u | GUI, networking only via the Firefox web browser, no file execution in /home or /tmp |
user_u | GUI and networking available |
staff_u | GUI, networking, and the sudo command available |
sysadm_u | GUI, networking, and the sudo and su commands available |
unconfined_u | Full system access |
DEBUG
First check to see if SEAlert is installed. dnf provides */sealert
Let's check journalctl and see if there are any alerts. journalctl | grep sealert
Find what you are looking for and run the the command it shows you, e.g., sealert -l 59cd7b4c-2b08-4bfc-8c15-4369f46c7355
Another way is to check the audit log for AVC errors. It's the most important source to debug SELinux problems. grep AVC /var/log/audit/audit.log
ausearch -m AVC -ts recent
Examples
semanage fcontext -a -t bin_t "/home/xymon/client/runclient.sh"
restorecon -v /home/xymon/client/runclient.sh
LOGS
SELinux generates alerts for system activities when it runs in enforcing or permissive mode. It writes the alerts to the /var/log/audit/audit.log file if the auditd daemon is running, or to the /var/log/messages file via the rsyslog daemon in the absence of auditd.