Note:
- This tutorial is available in an Oracle-provided free lab environment.
- It uses example values for Oracle Cloud Infrastructure credentials, tenancy, and compartments. When completing your lab, substitute these values with ones specific to your cloud environment.
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-labsGitHub 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_interpreterfor 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 Cloud Native Environment 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
oracleuser 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.
getenforceThe status should show as
Enforcing. -
Check the SELinux states and modes.
sestatusThe
sestatuscommand 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/passwdExample Output:
-rw-r--r--. 1 root root system_u:object_r:passwd_file_t:s0 1892 Apr 13 14:39 /etc/passwdThe
lsoutput with the-Zoption 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
targetedpolicy 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
headcommand limits the output to only the first ten lines.
The full output shows SELinux types exist for many different commands and services, such as
sshandsshd. - The
-
List the specific SELinux types.
The
grepwill 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
psgets the security labels for the processes.ps -efZ | grep sshdExample 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 sshdDifferent versions of Oracle Linux may provide more or less information when showing the labels of a specific process.
-
Use the
lscommand 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
sshddaemon process uses thesshd_ttype. Therefore, in the targeted policy, there is expected a rule for thesshd_tSELinux attribute that states objects withsshd_tcan access any objects with the following security attribute:etc_tsshd_key_t- …
Similarly, if we examine the
sshcommand, we can determine a similar mapping betweenssh_home_tandssh_exec_t.ls -lZ /usr/bin/sshExample Output:
-rwxr-xr-x. 1 root root system_u:object_r:ssh_exec_t:s0 775720 Oct 9 2021 /usr/bin/sshls -lZ ~/.sshExample 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
oracleuser.whoami id -ZExample 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 semanageThe results show that
/usr/sbin/semanageis part of thepolicycoreutils-python-utilspackage. -
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 sshExample 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
semanageto allow a custom port by adding a new policy rule.sudo semanage port -a -t ssh_port_t -p tcp 2222- The
-aoption adds a new policy rule of type-t.
- The
-
Check what ports SELinux allows now.
sudo semanage port -l | grep sshExample 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 443Example Output:
[oracle@ol-node-01 ~]$ sudo semanage port -a -t ssh_port_t -p tcp 443 Port tcp/443 already defined, modifying insteadThe warning occurred because we were trying to switch port 443 from the
http_port_ttype to thessh_port_ttype.To make this work without returning a warning, use the
-moption, 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
oracleuser is not listed and thus maps to theunconfined_uuser.
- 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_uonly occur after login and not by performing asudoorsu.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 -ZExample 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 axZThe output shows user ralph mapped to
guest_uand can log in. However, ralph should not be able to access the network. -
Test network connectivity with
ping.ping localhostExample Output:
ping: socket: Permission denied -
Additionally, test the network using
curl.curl ifconfig.meExample Output:
curl: (6) Could not resolve host: ifconfig.meThe message indicates that
curlcannot resolve the DNS name ofifconfig.meto an IP address. DNS, a Linux network service, requires opening a socket, so the SELinuxguest_uuser 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 -lExample 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 -aExample 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 -AExample 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 -ATExample Output:
allow user_t ping_t:process transition; [ selinuxuser_ping ]:TrueThe transition is allowed if the
user_pingSELinux 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 sambaExample Output:
virt_use_samba (off , off) Allow virt to use samba -
Change the boolean to enabled.
sudo setsebool virt_use_samba onor
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 -CExample Output:
SELinux boolean State Default Description virt_use_samba (on , on) Allow virt to use sambaThe 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 /webExample 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 /webExample 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 fcontextcommand. The-aadds a record to the file/etc/selinux/targeted/contexts/files/file_contexts.local, and-tdefines 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 /webExample 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 file3Notice the context did not change, which we expected.
-
Show the context of the newly created files and directories.
sudo semanage fcontext -C -lExample 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 /webExample 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
Summary
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.
For More Information
More Learning Resources
Explore other labs on docs.oracle.com/learn or access more free learning content on the Oracle Learning YouTube channel. Additionally, visit education.oracle.com/learning-explorer to become an Oracle Learning Explorer.
For product documentation, visit Oracle Help Center.