Note:

Use SELinux on Oracle Linux

Introduction

SELinux is a set of kernel mods and user-space tools that provide another layer of system security, precise access control, system-wide admin-defined policies, and improved mitigation for privilege escalation attacks.

This tutorial guides you through using these user-space tools to help keep your system running in enforcing mode.

Objectives

In this lab, you’ll learn to:

Prerequisites

Setup Lab Environment

Note: When using the free lab environment, see Oracle Linux Lab Basics for connection and other usage instructions.

Create a User

An additional user allows testing the assignment of an SELinux user later in this lab.

  1. If not already connected, open a terminal and connect via ssh to the ol8-server system.

    ssh oracle@<ip_address_of_ol8-server>
    
  2. Create a user and set a password.

    sudo useradd -u 8000 ralph
    echo "ralph:oracle" | sudo chpasswd
    
  3. 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
    
  4. Open a new terminal and verify the SSH connection works.

    ssh ralph@<ip_address_of_ol8-server>
    

    Then exit the session, and close the terminal window.

SELinux Mode and Status

Oracle Linux installs SELinux by default and runs in Enforcing mode.

  1. Confirm by checking the SELinux mode.

    It should be set to Enforcing.

    getenforce
    
  2. 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 an 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.

  1. 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).

  2. Get a listing of the available SELinux types.

    seinfo --type | head
    
    • The head command limits the output to only the first ten output lines.

    The full output shows SELinux types exist for many different commands and services, such as ssh and sshd.

  3. Get a listing of specific SELinux types.

    The grep will limit the output to only those types containing the word ssh.

    seinfo -t | grep ssh
    
  4. Get a listing of the security lables 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 2535      1  0 14:37 ?        00:00:00 /usr/sbin/sshd -D
    system_u:system_r:sshd_t:s0-s0:c0.c1023 root 18514  2535  0 15:21 ?        00:00:00 sshd: oracle [priv]
    unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 oracle 18528 18514  0 15:21 ? 00:00:00 sshd: oracle@pts/0
    unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 oracle 23611 18529  0 15:41 pts/0 00:00:00 grep --color=auto sshd
    

    Using ls gets 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 the sshd_t type. Therefore, in the targeted policy, there is expected a rule for the sshd_t SELinux attribute that states objects with sshd_t can access any objects with the following security attribute:

    • etc_t
    • sshd_key_t

    Similarly, if we were to examine the ssh command, we would be able to determine a similar mapping between ssh_home_t and ssh_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
    
  5. Get 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@ol-selinux ~]$ whoami
    oracle
    [oracle@ol-selinux ~]$ id -Z
    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 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. Oracle Linux doesn’t install the utility by default, so install it.

  1. Determine which package provides the utility.

    sudo dnf whatprovides semanage
    

    The results show that /usr/sbin/semanage is part of the policycoreutils-python-utils package.

  2. Install the package and any dependencies.

    sudo dnf install -y policycoreutils-python-utils
    
  3. Check what ports SELinux allows for sshd.

    sudo semanage port -l | grep ssh
    

    Example Output:

    ssh_port_t                     tcp      22
    
  4. Add a new port to the SELinux policy.

    If we were to change the port the SSH daemon listens on to 2222 or change 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 sudo semanage port -a -t ssh_port_t -p tcp 2222
    
    • The -a option adds a new policy rule of type -t.
  5. Check what ports SELinux allows now.

    sudo semanage port -l | grep ssh
    

    Example Output:

    ssh_port_t                     tcp      2222, 22
    
  6. 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 error with a message that the port is already in use.

    sudo semanage port -a -t ssh_port_t -p tcp 443
    

    Example Output:

    ValueError: Port tcp/443 already defined
    

    The error occurred because we are trying to switch port 443 from the http_port_t type to the ssh_port_t type. For this to work, use the -m option, which modifies the port object record.

    sudo semanage port -m -t ssh_port_t -p tcp 443
    

SELinux Users

Each Linux user is mapped to an 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.

  1. Get a listing of all the current Linux user mappings.

    sudo semanage login -l
    
    • Notice that our oracle user is not listed and thus maps to the unconfined_u user.
  2. Get a listing of the SELinux users.

    seinfo -u
    
  3. Restrict a user’s actions.

    Although a default Linux user runs unconstrained, the user’s actions may induce restrictions based on an applications domain. The domain 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.

    1. Create the new mapping to guest_u.

      sudo semanage login -a -s guest_u ralph
      
    2. Verify the mapping.

      sudo semanage login -l
      
    3. Test that ralph cannot access the network.

      The restrictions inherited from guest_u only occur after login and not by performing a sudo or su.

      Open a new terminal and connect via ssh to the ol8-server system as the ralph user.

      ssh ralph@<ip_address_of_ol8-server>
      
    4. 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
      
    5. 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.

    6. Test network connectivity with ping.

      ping localhost
      

      Example Output:

      ping: socket: Permission denied
      
    7. 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 of ifconfig.me to an IP address. DNS, a Linux network service, requires opening a socket, so the SELinux guest_u user blocks it.

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

  1. Get a list of booleans along with their meaning.

    Switch back to the terminal where you are logged in as oracle and run the following command.

    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 enabled (on) or disabled (off).
  2. 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
    ...
    
  3. Get the status of a single boolean.

    If the boolean name is known, pass the name as an argument to only get that booleans status.

    sudo getsebool virt_use_nfs
    
  4. 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
    ...
    
  5. 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.
  6. Enable a boolean.

    Suppose we want to allow KVM to store images on a Samba share? There’s a boolean for that too.

    1. Find the boolean.

      sudo semanage boolean -l | grep virt | grep samba
      

      Example Output:

      virt_use_samba                 (off  ,  off)  Allow virt to use samba
      
    2. Change the boolean to enabled.

      sudo setsebool virt_use_samba on
      

      or

      sudo semanage boolean -m --on virt_use_samba
      
    3. Check the current status.

      getsebool virt_use_samba
      
    4. Ensure the change survives a reboot.

      sudo setsebool -P virt_use_samba on
      
  7. 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 making the switch permanent and writing the pending values to the policy file on disk.

SELinux File Context

All files and directories get 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.

  1. Create the new directory along with three files.

    sudo mkdir -p /web
    sudo touch /web/file{1,2,3}
    
  2. 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.

  3. 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
    
  4. Return labels to default settings.

    Switch the context back to the default context type.

    sudo restorecon -R -v /web/
    

    Example Output:

    [oracle@ol-selinux ~]$ sudo restorecon -R -v /web/
    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
    [oracle@ol-selinux ~]$ ls -lZ /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
    
  5. Make label changes permanent.

    In order 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, it’s recommended to use the full path to the file or directory to avoid mislabeling files after a file system relabeling or after running restorecon.

  6. Check the context.

    ls -ldZ /web; ls -lZ /web
    

    Example Output:

    [oracle@ol-selinux ~]$ ls -ldZ /web; ls -lZ /web
    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.

  7. Show the context of the newly created files and directories.

    sudo semanage fcontext -C -l
    

    Example Output:

    [oracle@ol-selinux ~]$ sudo semanage fcontext -C -l
    SELinux fcontext                                   type               Context
    
    /web(/.*)?                                         all files          system_u:object_r:httpd_sys_content_t:s0 
    
  8. Apply the changes to the context.

    sudo restorecon -R -v /web
    

    Example Output:

    [oracle@ol-selinux ~]$ sudo restorecon -R -v /web
    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
    
  9. 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.
  10. Apply the changes and verify the context returned to default_t.

    sudo restorecon -R -v /web; ls -ldZ /web; ls -lZ /web
    

Check out the man pages for the utilities shown. Then use what you learned to keep SELinux in Enforcing mode.

For More Information

See other related resources:

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.