1 of 3

SELinux BasicsLesson 1 of 3

SELinux modes and security contexts

Understand what SELinux adds, check and change its mode, and read the context on files, processes and users.

  • getenforce
  • setenforce
  • sestatus
  • /etc/selinux/config
  • ls -Z
  • ps -eZ
  • id -Z
  • matchpathcon

40 min5 exercises

After this lesson you can

  • Explain in a few sentences why SELinux can block something that file permissions allow.
  • Read the current mode, change it for now with setenforce, and make the change survive a reboot in /etc/selinux/config.
  • Read a context such as system_u:object_r:httpd_sys_content_t:s0 and say which part decides access.

The idea

Ordinary Linux permissions answer: does this user have read, write or execute on this file? That is discretionary access control: the owner decides, and any process running as root can do anything. SELinux adds mandatory access control on top. The system policy decides which process type may touch which object type, whatever the user ID, and even root is confined.

An example: the web server httpd is allowed to read files labelled httpd_sys_content_t. If it is exploited and tries to read /etc/shadow (labelled shadow_t) or your home directory (user_home_t), SELinux refuses, although httpd could read them by ordinary permissions. Both checks must pass: first the normal mode bits, then SELinux.

Modes

ModeBehaviour
EnforcingPolicy is applied: violations are blocked and logged. The right setting for production and the exam
PermissiveViolations are only logged. For diagnosis (“is SELinux the cause?”)
DisabledNo SELinux at all. Avoid
TaskCommand
Current modegetenforce, sestatus
Change now (lost at reboot)setenforce 0 (permissive), setenforce 1 (enforcing)
Change for every bootSELINUX=enforcing or permissive in /etc/selinux/config

The two are independent: setenforce does not edit the file and the file does not change the running system until reboot. A task phrased “must remain after reboot” needs the file. The targeted policy confines selected network-facing services; all else runs unconfined.

Contexts

Every file, process, port and user has a context: four colon-separated fields.

system_u : object_r : httpd_sys_content_t : s0
 user      role        type                 level

For the targeted policy everything that matters is the type: a process type (httpd_t) is allowed or denied access to object types (httpd_sys_content_t). The user and role fields are mostly fixed, and the level (s0) is for MLS/MCS and is usually ignored.

WhatCommand
Files and directoriesls -Z, ls -Zd DIR
Processesps -eZ, ps -Z PID
Your userid -Z
What the policy says a path should bematchpathcon PATH

A new file takes the context of its parent directory. A file that is moved (mv) keeps its old label; a copied file (cp) takes the label of its new location. That difference explains most “I moved it to the web root and now it’s forbidden” problems.

Try it

getenforce
sestatus
Enforcing
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:      33

Switch it for now, then for good

sudo setenforce 0
getenforce
sudo setenforce 1
Permissive
sudo sed -i 's/^SELINUX=.*/SELINUX=permissive/' /etc/selinux/config
grep -E '^SELINUX=' /etc/selinux/config
SELINUX=permissive

Restore it the same way (enforcing) before finishing.

Read contexts

ls -Zd /etc/passwd /var/www/html /home
ps -Z $$
id -Z
system_u:object_r:passwd_file_t:s0 /etc/passwd
system_u:object_r:httpd_sys_content_t:s0 /var/www/html
system_u:object_r:home_root_t:s0 /home
LABEL                                    PID TTY      STAT   TIME COMMAND
unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 4120 pts/0 Ss 0:00 -bash
unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023

Your interactive shell is unconfined_t: not restricted by the targeted policy. Services such as httpd_t and sshd_t are.

What should it be?

echo hi | sudo tee /tmp/page.html /var/www/html/page.html
ls -Z /tmp/page.html /var/www/html/page.html
matchpathcon /var/www/html/page.html
unconfined_u:object_r:user_tmp_t:s0 /tmp/page.html
unconfined_u:object_r:httpd_sys_content_t:s0 /var/www/html/page.html
/var/www/html/page.html	system_u:object_r:httpd_sys_content_t:s0

The file created in /var/www/html inherited httpd_sys_content_t from the directory. The one in /tmp did not, and if you mv it into the web root it would keep user_tmp_t, which httpd may not read.

Going further

sestatus -v shows the labels of important files and processes. seinfo and sesearch -A -s httpd_t -t httpd_sys_content_t (package setools-console) query the policy itself: they show exactly what httpd_t is allowed to do with that type. getenforce inside a container reports the host’s mode. ls -Z and ps -Z are the first thing to run in every SELinux investigation, because most denials are wrong labels. Other policies (minimum, mls) exist, but targeted is the RHEL default.

Practice

0 of 5 done

Do these on your own system. They get harder. Check each result, then tick it off.

  1. Warm-up

    What mode is SELinux in?

    Show the current SELinux mode, the mode configured for the next boot, and the policy name, using two different commands.

    Check your result

    getenforce prints Enforcing. sestatus shows Current mode: enforcing, Mode from config file: enforcing and Loaded policy name: targeted.

    Hint

    getenforce is the short form. sestatus shows everything. The persistent setting is the SELINUX= line in /etc/selinux/config.

    Solution
    getenforce
    sestatus
    grep -E '^SELINUX=' /etc/selinux/config
  2. Practice

    Switch to permissive and back

    Put SELinux into permissive mode immediately without editing any file, verify, and return to enforcing. State what permissive does differently and why it is a diagnostic tool, not a fix.

    Check your result

    setenforce 0 makes getenforce print Permissive; setenforce 1 returns to Enforcing. In permissive mode violations are logged but not blocked.

    Hint

    setenforce 0|1 or Permissive|Enforcing. The change is lost at reboot.

    Solution
    getenforce
    sudo setenforce 0
    getenforce
    sudo setenforce 1
    getenforce
  3. Practice

    Make the mode persistent

    Configure the system so that SELinux is permissive after the next reboot. Verify the file, reboot, confirm, and then restore enforcing the same persistent way. Explain why setting it with setenforce is not enough for a task that says "at boot".

    Check your result

    grep ^SELINUX= /etc/selinux/config prints SELINUX=permissive. After a reboot getenforce prints Permissive. After restoring and rebooting it prints Enforcing.

    Hint

    Edit the SELINUX= line. Valid values: enforcing, permissive, disabled. Use sed -i to change only that line.

    Solution
    sudo sed -i 's/^SELINUX=.*/SELINUX=permissive/' /etc/selinux/config
    grep ^SELINUX= /etc/selinux/config
    sudo reboot
    # after the reboot
    getenforce
    sudo sed -i 's/^SELINUX=.*/SELINUX=enforcing/' /etc/selinux/config
    sudo reboot
  4. Practice

    Read a context

    Show the context of /etc/passwd, /var/www/html, /home, your shell process, and your own user. For one of them write out the four fields and say which one drives the access decision in the targeted policy.

    Check your result

    File contexts look like system_u:object_r:passwd_file_t:s0. The shell runs as unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023. The type (third field) is what the policy rules compare.

    Hint

    ls -Zd PATH, ps -Z, id -Z. The fields are user:role:type:level.

    Solution
    ls -Zd /etc/passwd /var/www/html /home
    ps -Z $$
    id -Z
  5. Challenge

    What should this file's label be?

    Create /tmp/page.html and /var/www/html/page.html with the same content. Compare their contexts, and ask the policy what the correct context of /var/www/html/page.html is. Explain what you would conclude if the actual and expected differed.

    Check your result

    matchpathcon /var/www/html/page.html prints the expected httpd_sys_content_t. A file in /tmp has user_tmp_t. A mismatch means the file was created elsewhere and moved, or labelled by hand.

    Hint

    matchpathcon (or semanage fcontext -l | grep PATH) reports what the policy says; ls -Z reports what is on disk.

    Solution
    echo hi | sudo tee /tmp/page.html /var/www/html/page.html
    ls -Z /tmp/page.html /var/www/html/page.html
    matchpathcon /var/www/html/page.html