Use SELinux on Oracle Linux
Introduction
SELinux, or Security-Enhanced Linux, is a set of kernel modifications and user-space tools designed to protect the Linux Operating System. SELinux is a Linux kernel security module that uses a mechanism called mandatory access controls (MAC) to provide another layer of system security, precise access control, system-wide admin-defined policies, and improved mitigation for privilege escalation attacks as defined by the system administrator.
This tutorial guides you through using these user-space tools to help keep your system running in enforcing mode.
Objectives
In this tutorial, you will learn how to:
- Check SELinux mode and status
- Understand SELinux security labels
- Work with SELinux network services
- Use SELinux users
- Change SELinux booleans
- Evaluate SELinux file contexts
Prerequisites
Minimum of a single Oracle Linux system
Each system should have Oracle Linux installed and configured with:
- A non-root user account with sudo access
- Access to the Internet
Deploy Oracle Linux
Note: If running in your own tenancy, read the linux-virt-labs
GitHub project README.md and complete the prerequisites before deploying the lab environment.
Open a terminal on the Luna Desktop.
Clone the
linux-virt-labs
GitHub project.git clone https://github.com/oracle-devrel/linux-virt-labs.git
Change into the working directory.
cd linux-virt-labs/ol
Install the required collections.
ansible-galaxy collection install -r requirements.yml
Deploy the lab environment.
ansible-playbook create_instance.yml -e localhost_python_interpreter="/usr/bin/python3.6"
The free lab environment requires the extra variable
local_python_interpreter
, which setsansible_python_interpreter
for plays running on localhost. This variable is needed because the environment installs the RPM package for the Oracle Cloud Infrastructure SDK for Python, located under the python3.6 modules.The default deployment shape uses the AMD CPU and Oracle Linux 8. To use an Intel CPU or Oracle Linux 9, add
-e instance_shape="VM.Standard3.Flex"
or-e os_version="9"
to the deployment command.Important: Wait for the playbook to run successfully and reach the pause task. At this stage of the playbook, the installation of Oracle Linux is complete, and the instances are ready. Take note of the previous play, which prints the public and private IP addresses of the nodes it deploys and any other deployment information needed while running the lab.
Create a New Test User
An additional user allows testing the assignment of a SELinux user later in this tutorial.
Open a terminal and connect via SSH to the ol-node-01 instance.
ssh oracle@<ip_address_of_instance>
Create a new user and set a password.
sudo useradd -u 8000 ralph echo "ralph:oracle" | sudo chpasswd
Allow SSH connections.
Copy the SSH key from the
oracle
user account.sudo mkdir /home/ralph/.ssh sudo cp /home/oracle/.ssh/authorized_keys /home/ralph/.ssh/authorized_keys sudo chown -R ralph:ralph /home/ralph/.ssh sudo chmod 700 /home/ralph/.ssh sudo chmod 600 /home/ralph/.ssh/authorized_keys
Open a new terminal and verify you can connect via SSH using the newly created user.
ssh ralph@<ip_address_of_instance>
Exit the session and close the terminal window.
exit
Switch to the terminal connected to ol-node-01 as the oracle user.
SELinux Mode and Status
Oracle Linux installs SELinux by default and runs in Enforcing
mode.
Confirm by checking the SELinux mode.
getenforce
The status should show as
Enforcing
.Check the SELinux states and modes.
sestatus
The
sestatus
command output shows the SELinux status, policy, and mode.Example Output:
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: 31
SELinux Security Labels
Every process and system resource under SELinux has a security label called a SELinux context. The SELinux context, also called an SELinux label, focuses on the security properties and ensures a consistent way to reference objects in the SELinux policy.
Show the SELinux security label for a file.
ls -ldZ /etc/passwd
Example Output:
-rw-r--r--. 1 root root system_u:object_r:passwd_file_t:s0 1892 Apr 13 14:39 /etc/passwd
The
ls
output with the-Z
option displays the four SELinux attribute fields:- user:
system_u
- role:
object_r
- type:
passwd_file_t
- security:
s0
The most important of these is the SELinux type, as the majority of SELinux
targeted
policy rules leverage SELinux types to define the allowed interaction between one object (e.g., process) and another (e.g., file).- user:
List all of the available SELinux types.
seinfo --type | head
- The
head
command limits the output to only the first ten lines.
The full output shows SELinux types exist for many different commands and services, such as
ssh
andsshd
.- The
List the specific SELinux types.
The
grep
will limit the output to only those types containing the wordssh
.seinfo -t | grep ssh
List the security labels for specific processes and configuration files.
Using
ps
gets the security labels for the processes.ps -efZ | grep sshd
Example Output:
system_u:system_r:sshd_t:s0-s0:c0.c1023 root 3343 1 0 10:52 ? 00:00:00 sshd: /usr/sbin/sshd -D [listener] 1 of 10-100 startups system_u:system_r:sshd_t:s0-s0:c0.c1023 root 11451 3343 0 11:09 ? 00:00:00 sshd: oracle [priv] unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 oracle 11466 11451 0 11:09 ? 00:00:00 sshd: oracle@pts/0 system_u:system_r:sshd_t:s0-s0:c0.c1023 root 11560 3343 0 11:11 ? 00:00:00 sshd: ralph [priv] unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 ralph 11574 11560 0 11:11 ? 00:00:00 sshd: ralph@pts/1 system_u:system_r:sshd_t:s0-s0:c0.c1023 root 11636 3343 0 11:12 ? 00:00:00 sshd: [accepted] system_u:system_r:sshd_net_t:s0-s0:c0.c1023 sshd 11637 11636 0 11:12 ? 00:00:00 sshd: [net] unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 oracle 11639 11467 0 11:12 pts/0 00:00:00 grep --color=auto sshd
Different versions of Oracle Linux may provide more or less information when showing the labels of a specific process.
Use the
ls
command to show the security labels for the configuration files.ls -lZ /etc/ssh/
Example Output:
total 600 -rw-r--r--. 1 root root system_u:object_r:etc_t:s0 577388 Oct 9 2021 moduli -rw-r--r--. 1 root root system_u:object_r:etc_t:s0 1770 Oct 9 2021 ssh_config drwxr-xr-x. 2 root root system_u:object_r:etc_t:s0 28 Feb 18 08:51 ssh_config.d -rw-------. 1 root root system_u:object_r:etc_t:s0 4268 Apr 13 14:37 sshd_config -rw-r-----. 1 root ssh_keys system_u:object_r:sshd_key_t:s0 537 Apr 13 14:37 ssh_host_ecdsa_key -rw-r--r--. 1 root root system_u:object_r:sshd_key_t:s0 197 Apr 13 14:37 ssh_host_ecdsa_key.pub -rw-r-----. 1 root ssh_keys system_u:object_r:sshd_key_t:s0 432 Apr 13 14:37 ssh_host_ed25519_key -rw-r--r--. 1 root root system_u:object_r:sshd_key_t:s0 117 Apr 13 14:37 ssh_host_ed25519_key.pub -rw-r-----. 1 root ssh_keys system_u:object_r:sshd_key_t:s0 2635 Apr 13 14:37 ssh_host_rsa_key -rw-r--r--. 1 root root system_u:object_r:sshd_key_t:s0 589 Apr 13 14:37 ssh_host_rsa_key.pub
The
sshd
daemon process uses thesshd_t
type. Therefore, in the targeted policy, there is expected a rule for thesshd_t
SELinux attribute that states objects withsshd_t
can access any objects with the following security attribute:etc_t
sshd_key_t
- ...
Similarly, if we examine the
ssh
command, we can determine a similar mapping betweenssh_home_t
andssh_exec_t
.ls -lZ /usr/bin/ssh
Example Output:
-rwxr-xr-x. 1 root root system_u:object_r:ssh_exec_t:s0 775720 Oct 9 2021 /usr/bin/ssh
ls -lZ ~/.ssh
Example Output:
total 4 -rw-------. 1 oracle oracle unconfined_u:object_r:ssh_home_t:s0 404 Apr 13 14:39 authorized_keys
Display the security context of a user.
The other context type of interest is
unconfined_t
. Objects with this SELinux type, such as users, have unrestricted access. This level of access means SELinux doesn't limit what users can do and only inhibits them through DAC permissions. DAC (Discretionary Access Control) is the security policy handled by traditional users, groups, and other permissions.For example, show the security attributes for the
oracle
user.whoami id -Z
Example Output:
oracle unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
SELinux and Network Services
SELinux tracks the configurations for the most commonly used network-based software packages within its internal database. This tracking allows SELinux to protect the system from externally-facing services that are prone to attacks.
Therefore, SELinux may prevent a service from working if you configure the software to use a non-standard directory or port.
To show what SELinux knows about a system's standard ports, we need to use the SELinux utility semanage
.
Determine which package provides the utility.
sudo dnf whatprovides semanage
The results show that
/usr/sbin/semanage
is part of thepolicycoreutils-python-utils
package.Install the package and any dependencies.
sudo dnf install -y policycoreutils-python-utils
Check what ports SELinux allows for
sshd
.sudo semanage port -l | grep ssh
Example Output:
ssh_port_t tcp 22
Add a new port to the SELinux policy.
If we were to change the port the SSH daemon listens on to 2222 or where it stores the default configuration; then we would need to inform SELinux that we want those changes. We can again use
semanage
to allow a custom port by adding a new policy rule.sudo semanage port -a -t ssh_port_t -p tcp 2222
- The
-a
option adds a new policy rule of type-t
.
- The
Check what ports SELinux allows now.
sudo semanage port -l | grep ssh
Example Output:
ssh_port_t tcp 2222, 22
Modify a port in the SELinux policy.
Let's say we wanted to map the SSH daemon to port 443. Repeat the same command, but it will warn that the port is already in use and indicate that it will modify it instead.
sudo semanage port -a -t ssh_port_t -p tcp 443
Example Output:
[oracle@ol-node-01 ~]$ sudo semanage port -a -t ssh_port_t -p tcp 443 Port tcp/443 already defined, modifying instead
The warning occurred because we were trying to switch port 443 from the
http_port_t
type to thessh_port_t
type.To make this work without returning a warning, use the
-m
option, which modifies the port object record rather than trying to add it.sudo semanage port -m -t ssh_port_t -p tcp 443
SELinux Users
Each Linux user is mapped to a SELinux user using an SELinux policy. This approach allows Linux users to inherit restrictions based on their SELinux user mapping. The default mapping in Oracle Linux is the __default__
login, which maps to the SELinux unconfined_u
user.
List all the current Linux user mappings.
sudo semanage login -l
- Notice that our
oracle
user is not listed and thus maps to theunconfined_u
user.
- Notice that our
Listing the current SELinux users.
seinfo -u
Restrict a user's actions.
Although a default Linux user runs unconstrained, the user's actions may induce restrictions based on an application's
domain
, which is a bunch of objects with the same SELinux type.What if we wanted to block users from using the X Window System,
sudo
, and the network?SELinux has a user for that.
To verify this, we need to have another Linux user. We'll use the user ralph.
Create the new mapping to
guest_u
.sudo semanage login -a -s guest_u ralph
Verify the mapping.
sudo semanage login -l
Test that ralph cannot access the network.
The restrictions inherited from
guest_u
only occur after login and not by performing asudo
orsu
.Open a new terminal and connect via SSH to the instance as the ralph user.
ssh ralph@<ip_address_of_instance>
Check the user's context.
id; id -Z
Example Output:
uid=8000(ralph) gid=8000(ralph) groups=8000(ralph) context=guest_u:guest_r:guest_t:s0 guest_u:guest_r:guest_t:s0
Show the security context of the user’s current processes:
ps axZ
The output shows user ralph mapped to
guest_u
and can log in. However, ralph should not be able to access the network.Test network connectivity with
ping
.ping localhost
Example Output:
ping: socket: Permission denied
Additionally, test the network using
curl
.curl ifconfig.me
Example Output:
curl: (6) Could not resolve host: ifconfig.me
The message indicates that
curl
cannot resolve the DNS name ofifconfig.me
to an IP address. DNS, a Linux network service, requires opening a socket, so the SELinuxguest_u
user blocks it.Close the current terminal window.
We finished testing with the user ralph, so close that terminal window.
exit
SELinux Booleans
SELinux booleans allow specific policy changes at runtime without knowing how to write SELinux policies. Oracle Linux provides many built-in booleans, or administrators familiar with SELinux policies may write their own. Administrators are encouraged to write policies as booleans if the policy implemented is optional.
Return a list of booleans along with their meaning.
sudo semanage boolean -l
Example Output:
SELinux boolean State Default Description abrt_anon_write (off , off) Allow abrt to anon write abrt_handle_event (off , off) Allow abrt to handle event abrt_upload_watch_anon_write (on , on) Allow abrt to upload watch anon write antivirus_can_scan_system (off , off) Allow antivirus to can scan system antivirus_use_jit (off , off) Allow antivirus to use jit auditadm_exec_content (on , on) Allow auditadm to exec content authlogin_nsswitch_use_ldap (off , off) Allow authlogin to nsswitch use ldap authlogin_radius (off , off) Allow authlogin to radius ...
The output explains what each boolean does and whether it is enabled (
on
) or disabled (off
).Get a list of just the booleans and their status.
sudo getsebool -a
Example Output:
abrt_anon_write --> off abrt_handle_event --> off abrt_upload_watch_anon_write --> on antivirus_can_scan_system --> off antivirus_use_jit --> off auditadm_exec_content --> on authlogin_nsswitch_use_ldap --> off authlogin_radius --> off authlogin_yubikey --> off ...
Get the status of a single boolean.
If the boolean name is known, pass the name as an argument to get that specific boolean's status.
sudo getsebool virt_use_nfs
Query the SELinux policy for a boolean.
Ever wonder what a boolean triggers within the SELinux policy? SELinux provides a utility to query those rules.
sesearch -b virt_use_nfs -A
Example Output:
allow fsdaemon_t autofs_t:dir { getattr open search }; [ virt_use_nfs ]:True allow fsdaemon_t nfs_t:dir { getattr ioctl lock open read search }; [ virt_use_nfs ]:True allow fsdaemon_t nfs_t:dir { getattr ioctl lock open read search }; [ virt_use_nfs ]:True allow fsdaemon_t nfs_t:dir { getattr ioctl lock open read search }; [ virt_use_nfs ]:True allow fsdaemon_t nfs_t:dir { getattr open search }; [ virt_use_nfs ]:True allow fsdaemon_t nfs_t:dir { getattr open search }; [ virt_use_nfs ]:True allow fsdaemon_t nfs_t:file { getattr ioctl lock open read }; [ virt_use_nfs ]:True allow fsdaemon_t nfs_t:lnk_file { getattr read }; [ virt_use_nfs ]:True ...
Query if a boolean allows access.
What about if particular access is allowed based on a conditional boolean? Answer the question: Does user ping permit the transition from a user domain (
user_t
) to the ping domain (ping_t
)?sesearch -s user_t -t ping_t -c process -p transition -AT
Example Output:
allow user_t ping_t:process transition; [ selinuxuser_ping ]:True
The transition is allowed if the
user_ping
SELinux boolean is enabled.Enable a boolean.
Suppose we want to allow KVM to store images on a Samba share. There's a boolean for that too.
Find the boolean.
sudo semanage boolean -l | grep virt | grep samba
Example Output:
virt_use_samba (off , off) Allow virt to use samba
Change the boolean to enabled.
sudo setsebool virt_use_samba on
or
sudo semanage boolean -m --on virt_use_samba
Check the current status.
getsebool virt_use_samba
Ensure the change survives a reboot.
sudo setsebool -P virt_use_samba on
Show local SELinux policy customizations.
Knowing that we have changed the default settings, we can show those local customizations.
sudo semanage boolean -l -C
Example Output:
SELinux boolean State Default Description virt_use_samba (on , on) Allow virt to use samba
The output shows that the default value is now
on
. The default value changed after the switch was made permanent and the pending values were written to the policy file on disk.
SELinux File Context
All files and directories are labeled with an SELinux context when running SELinux. We'll examine a few commands for managing the file system labeling.
One familiar example is creating a new directory for Nginx's document root.
Create the new directory along with three files.
sudo mkdir -p /web sudo touch /web/file{1,2,3}
Check the new directory and file labeling.
ls -lZ /web
Example Output:
total 0 -rw-r--r--. 1 root root unconfined_u:object_r:default_t:s0 0 Apr 14 19:00 file1 -rw-r--r--. 1 root root unconfined_u:object_r:default_t:s0 0 Apr 14 19:00 file2 -rw-r--r--. 1 root root unconfined_u:object_r:default_t:s0 0 Apr 14 19:00 file3
- The new directory's context type and the files are
default_t
.
Note: Newly created files and directories inherit the SELinux type of their parent directories.
- The new directory's context type and the files are
Make temporary label changes.
As part of troubleshooting or testing, we can temporarily change the context.
sudo chcon -R -t httpd_sys_content_t /web/
ls -lZ /web
Return labels to default settings.
Switch the context back to the default context type.
sudo restorecon -R -v /web/
Example Output:
Relabeled /web from unconfined_u:object_r:httpd_sys_content_t:s0 to unconfined_u:object_r:default_t:s0 Relabeled /web/file1 from unconfined_u:object_r:httpd_sys_content_t:s0 to unconfined_u:object_r:default_t:s0 Relabeled /web/file2 from unconfined_u:object_r:httpd_sys_content_t:s0 to unconfined_u:object_r:default_t:s0 Relabeled /web/file3 from unconfined_u:object_r:httpd_sys_content_t:s0 to unconfined_u:object_r:default_t:s0
Verify the change.
ls -lZ /web
Example Output:
total 0 -rw-r--r--. 1 root root unconfined_u:object_r:default_t:s0 0 Apr 14 19:00 file1 -rw-r--r--. 1 root root unconfined_u:object_r:default_t:s0 0 Apr 14 19:00 file2 -rw-r--r--. 1 root root unconfined_u:object_r:default_t:s0 0 Apr 14 19:00 file3
Make label changes permanent.
To make the changes permanent and survive a reboot, use the
semanage fcontext
command. The-a
adds a record to the file/etc/selinux/targeted/contexts/files/file_contexts.local
, and-t
defines the type.sudo semanage fcontext -a -t httpd_sys_content_t "/web(/.*)?"
Note: When changing the SELinux context with
semanage fcontext
, using the full path to the file or directory is recommended to avoid mislabeling files after a file system relabeling or runningrestorecon
.Check the context.
ls -ldZ /web; ls -lZ /web
Example Output:
drwxr-xr-x. 2 root root unconfined_u:object_r:default_t:s0 45 Apr 14 19:00 /web total 0 -rw-r--r--. 1 root root unconfined_u:object_r:default_t:s0 0 Apr 14 19:00 file1 -rw-r--r--. 1 root root unconfined_u:object_r:default_t:s0 0 Apr 14 19:00 file2 -rw-r--r--. 1 root root unconfined_u:object_r:default_t:s0 0 Apr 14 19:00 file3
Notice the context did not change, which we expected.
Show the context of the newly created files and directories.
sudo semanage fcontext -C -l
Example Output:
SELinux fcontext type Context /var/oled/pcp(/.*)? all files system_u:object_r:pcp_log_t:s0 /web(/.*)? all files system_u:object_r:httpd_sys_content_t:s0 SELinux Local fcontext Equivalence /opt/rh/gcc-toolset-11/root = / /opt/rh/gcc-toolset-13/root = /
Apply the changes to the context.
sudo restorecon -R -v /web
Example Output:
Relabeled /web from unconfined_u:object_r:default_t:s0 to unconfined_u:object_r:httpd_sys_content_t:s0 Relabeled /web/file1 from unconfined_u:object_r:default_t:s0 to unconfined_u:object_r:httpd_sys_content_t:s0 Relabeled /web/file2 from unconfined_u:object_r:default_t:s0 to unconfined_u:object_r:httpd_sys_content_t:s0 Relabeled /web/file3 from unconfined_u:object_r:default_t:s0 to unconfined_u:object_r:httpd_sys_content_t:s0
Remove the new SELinux context.
sudo semanage fcontext -d "/web(/.*)?"
This example passes the regular expression used when creating the context and places it at the beginning of the context record on file. Since it's a regular expression, enclose it within quotes.
Apply the changes and verify the context returned to
default_t
.sudo restorecon -R -v /web; ls -ldZ /web; ls -lZ /web
Next Steps
This concludes the walkthrough demonstrating how to use these user-space tools. Check out the man
pages for the utilities shown. Then, use what you learned to keep SELinux in Enforcing
mode.