List and Identify
SELinux File and Process Context

List and identify SELinux file and process context

CIS126RH | RHEL System Administration 1
Mesa Community College

SELinux makes access control decisions based on security contexts — labels applied to every file, process, port, and user on the system. Understanding how to read and interpret these labels is the foundation of SELinux administration. The -Z flag added to familiar commands like ls, ps, and id reveals SELinux contexts. The matchpathcon and semanage fcontext tools show the expected context for file paths. Reading contexts fluently is tested on the RHCSA exam.

Learning Objectives

  1. Explain the SELinux security context structure — Decode the four components of a security context (user, role, type, level) and identify which component matters most for policy decisions
  2. List SELinux contexts for files and directories — Use ls -Z and ls -lZ to display security contexts for files, directories, and symlinks
  3. List SELinux contexts for processes — Use ps -Z and ps auxZ to display the security context of running processes
  4. Identify expected contexts and diagnose mismatches — Use matchpathcon, semanage fcontext -l, and ausearch to find correct contexts and diagnose why a context is causing an access denial

The Security Context Structure

Every SELinux context has four colon-separated components. The type is the most important for day-to-day administration.

# A complete security context:
system_u:object_r:httpd_sys_content_t:s0
#   ^         ^              ^            ^
# user     role            type        level

# Breaking down each component:
Component Position Purpose Common values
User1stSELinux user identity — maps to Linux userssystem_u, unconfined_u
Role2ndSELinux role — determines allowed typesobject_r (files), system_r (processes)
Type3rdThe primary policy decision point — what can access whathttpd_t, httpd_sys_content_t, sshd_t
Level4thMLS/MCS sensitivity level — usually s0 on targeted systemss0, s0:c0,c1
The type is what matters for the RHCSA exam

Policy rules are written as: "processes of type X can perform action Y on objects of type Z." When diagnosing SELinux problems, focus on identifying the type of the process and the type of the file — that mismatch is the problem.

Listing File Contexts: ls -Z

The -Z flag added to ls displays the SELinux security context for each file and directory.

# Show security context alongside file listing
$ ls -Z /var/www/html/
system_u:object_r:httpd_sys_content_t:s0 index.html
system_u:object_r:httpd_sys_content_t:s0 images

# Combined: long listing + security context
$ ls -lZ /var/www/html/
-rw-r--r--. root root system_u:object_r:httpd_sys_content_t:s0 index.html
drwxr-xr-x. root root system_u:object_r:httpd_sys_content_t:s0 images

# Show context of a specific file
$ ls -Z /etc/shadow
system_u:object_r:shadow_t:s0 /etc/shadow

# Show context of a directory itself (not its contents)
$ ls -Zd /var/www/html
system_u:object_r:httpd_sys_content_t:s0 /var/www/html

# Show all files including hidden ones with context
$ ls -laZ /etc/ssh/
system_u:object_r:sshd_key_t:s0 ssh_host_rsa_key
system_u:object_r:etc_t:s0     sshd_config

Common File Type Labels

The type component determines which processes can access a file. Knowing the correct type for each location is essential for diagnosing mismatches.

File path / location Expected SELinux type Accessible by
/var/www/html/httpd_sys_content_tApache web server (httpd_t)
/etc/httpd/httpd_config_tApache configuration
/var/log/httpd/httpd_log_tApache log files
/etc/ssh/etc_t, sshd_key_tSSH server config and keys
/var/log/var_log_tSystem logging daemons
/home/user/user_home_tUser's own files
/tmp/tmp_tAll processes (temporary files)
/etc/etc_tSystem configuration
/usr/sbin/httpdhttpd_exec_tEntry point for httpd_t domain
/var/lib/mysql/mysqld_db_tMariaDB/MySQL database files

Listing Process Contexts: ps -Z

The -Z flag added to ps displays the SELinux context of running processes — showing the domain each process is running in.

# Show SELinux context for all processes
$ ps -Z
LABEL                          PID   TTY   TIME    CMD
unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023  1234  pts/0  00:00:00  bash

# Show context for a specific service
$ ps auxZ | grep httpd
system_u:system_r:httpd_t:s0     root    1234  ... /usr/sbin/httpd -DFOREGROUND
system_u:system_r:httpd_t:s0     apache  1235  ... /usr/sbin/httpd -DFOREGROUND

# Show context for sshd
$ ps auxZ | grep sshd
system_u:system_r:sshd_t:s0      root    877  ... /usr/sbin/sshd -D

# Show context for system daemon processes
$ ps -eZ | grep chronyd
system_u:system_r:chronyd_t:s0   chrony  1234  ... /usr/sbin/chronyd -F 2

# View context of the current shell
$ id -Z
unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023

User Context: id -Z and Other Tools

# View the SELinux context of the current user/process
$ id -Z
unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
# Regular users on RHEL 9 run as unconfined_t — no policy restrictions

# View context of the current process
$ cat /proc/self/attr/current
unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023

# After sudo — still unconfined for regular sudo users
$ sudo id -Z
unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023

# A confined service process context (run as that service's user)
$ sudo -u apache id -Z
system_u:system_r:httpd_t:s0

# Show the SELinux context of a port
$ sudo semanage port -l | grep http
http_port_t                    tcp      80, 443, 488, 8008, 8009, 8443

Finding the Expected Context: matchpathcon

matchpathcon reports the default SELinux context that the policy expects for a given file path — without looking at the actual file.

# What context should /var/www/html/index.html have?
$ matchpathcon /var/www/html/index.html
/var/www/html/index.html    system_u:object_r:httpd_sys_content_t:s0

# What context should /etc/ssh/sshd_config have?
$ matchpathcon /etc/ssh/sshd_config
/etc/ssh/sshd_config    system_u:object_r:etc_t:s0

# Compare expected context with actual context
$ matchpathcon -V /var/www/html/index.html
/var/www/html/index.html verified.        ← contexts match

$ matchpathcon -V /var/www/html/moved_file.html
/var/www/html/moved_file.html has context
    unconfined_u:object_r:user_home_t:s0,
    should be
    system_u:object_r:httpd_sys_content_t:s0
# moved_file.html has the wrong type — it was moved from a home directory
matchpathcon -V verifies the current context against the policy

matchpathcon -V FILE compares the file's actual SELinux context with what the policy expects for that path. "verified" means the contexts match; an error message shows the mismatch. This is the fastest way to confirm a context problem.

semanage fcontext: The Context Database

semanage fcontext -l lists all file context rules in the SELinux policy — the rules that matchpathcon and restorecon use to determine the correct context.

# List all file context rules (very long output — pipe to grep)
$ sudo semanage fcontext -l | grep "/var/www"
/var/www(/.*)?              all files   system_u:object_r:httpd_sys_content_t:s0
/var/www/cgi-bin(/.*)?     all files   system_u:object_r:httpd_sys_script_t:s0

# Find the rule for a specific path
$ sudo semanage fcontext -l | grep "/etc/ssh"
/etc/ssh(/.*)?             all files   system_u:object_r:etc_t:s0
/etc/ssh/ssh_host.*_key    regular     system_u:object_r:sshd_key_t:s0

# Show only custom (non-policy) rules added by administrators
$ sudo semanage fcontext -l -C
(empty if no custom rules have been added)

# Find the rule for a specific file extension
$ sudo semanage fcontext -l | grep "/home"
/home                      directory   system_u:object_r:home_root_t:s0
/home/[^/]+                directory   system_u:object_r:user_home_dir_t:s0
/home/[^/]+(/.*)?          all files   system_u:object_r:user_home_t:s0

Diagnosing Context Mismatches: ausearch

When SELinux denies access, the denial message in the audit log contains the context information needed to diagnose the exact problem.

# View all recent AVC (Access Vector Cache) denials
$ sudo ausearch -m AVC -ts recent

# A typical denial — annotated
type=AVC msg=audit(...):
  avc: denied { read } for
  pid=1234 comm="httpd"
  name="index.html" dev="sda1" ino=67890
  scontext=system_u:system_r:httpd_t:s0        ← process type
  tcontext=system_u:object_r:user_home_t:s0   ← file type (WRONG)
  tclass=file permissive=0

# Read the denial:
# httpd (httpd_t) was denied READ access to a file labeled user_home_t
# httpd_t can only read httpd_sys_content_t — not user_home_t
# FIX: relabel the file to httpd_sys_content_t with restorecon

# Search for denials involving a specific process
$ sudo ausearch -m AVC -ts recent -c httpd

The Context Mismatch Pattern

The most common SELinux problem: a file has the wrong context because it was created in one location and moved or copied to another.

# SCENARIO: Web content created in home directory then moved to /var/www/html

# Step 1: Alice creates a file in her home directory
$ touch ~/page.html
$ ls -Z ~/page.html
unconfined_u:object_r:user_home_t:s0 /home/alice/page.html
# Context: user_home_t — correct for a home directory file

# Step 2: She moves it to the web root
$ sudo mv ~/page.html /var/www/html/
$ ls -Z /var/www/html/page.html
unconfined_u:object_r:user_home_t:s0 /var/www/html/page.html
# Context STILL user_home_t — mv preserves the original context

# Step 3: Apache cannot serve the file (wrong type)
# httpd_t can only read httpd_sys_content_t, not user_home_t

# Step 4: matchpathcon confirms the mismatch
$ matchpathcon -V /var/www/html/page.html
/var/www/html/page.html has context user_home_t, should be httpd_sys_content_t
mv preserves SELinux context; cp does not always

mv preserves the original file's SELinux context. cp typically assigns the context based on the destination directory's policy rules. This is why moving web content from a home directory always produces a context mismatch that must be fixed with restorecon.

Reading Contexts for Common Services

# Apache web server — files and process
$ ls -Zd /var/www/html
system_u:object_r:httpd_sys_content_t:s0 /var/www/html

$ ps auxZ | grep httpd
system_u:system_r:httpd_t:s0  ... httpd

# SSH server — config and process
$ ls -lZ /etc/ssh/
system_u:object_r:etc_t:s0        sshd_config
system_u:object_r:sshd_key_t:s0   ssh_host_ed25519_key

$ ps auxZ | grep sshd
system_u:system_r:sshd_t:s0  ... sshd

# System files — important contexts
$ ls -Z /etc/passwd /etc/shadow
system_u:object_r:passwd_file_t:s0  /etc/passwd
system_u:object_r:shadow_t:s0       /etc/shadow

# Check if contexts are correct for a whole directory
$ matchpathcon -V /var/www/html/*
/var/www/html/index.html verified.
/var/www/html/page.html has context user_home_t, should be httpd_sys_content_t

Context Listing Tools Summary

Command What it shows When to use
ls -Z FILEFile context(s)Check what context a file currently has
ls -Zd DIRDirectory's own contextCheck the context of a directory itself
ps -ZProcess contexts (current user's processes)See what domain a process is running in
ps auxZAll process contextsFind the context of any running service
id -ZCurrent user's contextConfirm the current shell's SELinux context
matchpathcon PATHExpected context from policyFind out what context a path should have
matchpathcon -V FILEActual vs expected context comparisonVerify if a file's context is correct
semanage fcontext -lAll file context rules in the policyBrowse the complete context database
ausearch -m AVC -ts recentRecent SELinux denialsFind what SELinux denied and the contexts involved

Context Identification Quick Reference

Task Command
Show file contextls -Z /path/to/file
Show file context (long format)ls -lZ /path/to/file
Show directory's own contextls -Zd /path/to/dir
Show all files including hiddenls -laZ /path/
Show all process contextsps auxZ
Show context of a specific processps auxZ | grep PROCESSNAME
Show current user's contextid -Z
Find expected context for a pathmatchpathcon /path/to/file
Verify file's context vs policymatchpathcon -V /path/to/file
Search policy context databasesudo semanage fcontext -l | grep PATTERN
View recent SELinux denialssudo ausearch -m AVC -ts recent
View human-readable denial explanationssudo sealert -a /var/log/audit/audit.log

Common Mistakes

Mistake What goes wrong Correct approach
Using ls -Z DIR instead of ls -Zd DIR Shows contexts of files inside DIR, not the DIR's own context Use ls -Zd DIRNAME to see the directory's own context
Ignoring the type component and focusing on user or role Missing the relevant information — the type is what policy decisions are based on Focus on the third colon-separated field: the type (e.g., httpd_sys_content_t)
Assuming a file has the correct context because it is in the right directory Context from a previous location persists after mv Always verify with matchpathcon -V FILE after moving files
Confusing the process context (scontext) and file context (tcontext) in AVC messages Trying to relabel the process instead of the file In AVC messages: scontext = the process doing the action; tcontext = the file being accessed (usually needs fixing)
Thinking unconfined_t processes have SELinux contexts but no restrictions Students add files for unconfined processes expecting context to matter unconfined_t processes bypass the targeted policy — context type does not restrict them
Using semanage fcontext -l without grep on the full output The output is thousands of lines — overwhelming without filtering Always pipe to grep: semanage fcontext -l | grep "/var/www"

Complete Context Diagnosis Workflow

Exam scenario: Apache cannot serve /var/www/html/report.html even though Unix permissions are correct. Diagnose using SELinux context tools.

# Step 1: Check what context the file actually has
$ ls -Z /var/www/html/report.html
unconfined_u:object_r:user_home_t:s0 /var/www/html/report.html
# user_home_t — clearly wrong for a web content file

# Step 2: Verify against the policy
$ matchpathcon -V /var/www/html/report.html
/var/www/html/report.html has context user_home_t,
should be system_u:object_r:httpd_sys_content_t:s0
# Confirmed: context is wrong — should be httpd_sys_content_t

# Step 3: Check what the Apache process is running as
$ ps auxZ | grep httpd
system_u:system_r:httpd_t:s0  ... httpd
# httpd_t cannot read user_home_t — policy denies it

# Step 4: Confirm with audit log
$ sudo ausearch -m AVC -ts recent -c httpd
avc: denied { read } scontext=httpd_t tcontext=user_home_t
# Diagnosis complete — fix: restorecon /var/www/html/report.html

Knowledge Check

Answer these before moving to the next slide.

  1. A file shows the context system_u:object_r:httpd_sys_content_t:s0. Name each of the four components and identify which one the SELinux policy uses for access control decisions.
  2. Write the command to display the SELinux context of the file /etc/ssh/sshd_config.
  3. Write the command to display the SELinux context of the /var/www/html directory itself (not its contents). What is the difference from the command without the -d flag?
  4. Write the command to show the SELinux context of all running httpd processes.
  5. A file at /var/www/html/page.html was moved from /home/alice/. Write the two commands to (a) find what context the file currently has, and (b) confirm what context it should have.
  6. In an AVC denial message, what do scontext and tcontext represent, and which one usually needs to be fixed?

Knowledge Check — Answers

  1. The context system_u:object_r:httpd_sys_content_t:s0: system_u = SELinux user, object_r = SELinux role, httpd_sys_content_t = SELinux type, s0 = MLS level. The type (third field) is what the SELinux policy uses for access control decisions.
  2. ls -Z /etc/ssh/sshd_config
  3. ls -Zd /var/www/html — the -d flag shows the context of the directory entry itself. Without -d, ls -Z /var/www/html shows the contexts of the files and subdirectories inside the directory, not the directory's own context.
  4. ps auxZ | grep httpd
  5. (a) ls -Z /var/www/html/page.html — shows the actual current context (will show user_home_t).
    (b) matchpathcon -V /var/www/html/page.html — compares actual context to the expected policy context, showing the mismatch.
  6. scontext (source context) = the SELinux context of the process performing the action — usually correct.
    tcontext (target context) = the SELinux context of the file or object being accessed — this is usually what needs to be fixed. The fix is to relabel the file (tcontext) to the correct type using restorecon.

Key Takeaways

  1. Security contexts have four components: user:role:type:level. The type is what policy decisions are based on. File types end in _t (e.g., httpd_sys_content_t). Process types (domains) also end in _t (e.g., httpd_t).
  2. Use the -Z flag with familiar commands to see contexts. ls -Z FILE → file context. ls -Zd DIR → directory's own context. ps auxZ | grep SERVICE → process domain. id -Z → current user's context.
  3. matchpathcon -V FILE confirms whether a context is correct. "verified" = context matches the policy. Any other output = mismatch. semanage fcontext -l | grep PATTERN shows all rules for a path pattern. Use both to diagnose wrong-context problems.
  4. mv preserves context; files moved from home dirs have wrong context. AVC denials show: scontext = the process (usually correct); tcontext = the file (usually needs fixing with restorecon). Use ausearch -m AVC -ts recent to find denials.

Graded Lab

  • Run ls -Z /var/www/html/ to view the contexts of web content files. Run ls -Zd /var/www/html to view the directory's own context. Confirm both show httpd_sys_content_t.
  • Run ps auxZ | grep httpd to view the context of the Apache process. Identify the domain (httpd_t). Run ps auxZ | grep sshd to see the sshd context. Run id -Z to see your own context (unconfined_t).
  • Create a test file in your home directory: touch ~/test.html. Check its context with ls -Z ~/test.html — it should show user_home_t. Move it to /var/www/html/. Check the context again — confirm it still shows user_home_t.
  • Run matchpathcon -V /var/www/html/test.html to confirm the mismatch. Observe the "has context" vs "should be" output. Run sudo semanage fcontext -l | grep "/var/www/html" to see the policy rule for that directory.
  • Use sudo ausearch -m AVC -ts recent to look for any recent SELinux denials. If Apache is running, try to access the test.html file through a browser or curl — observe the denial in the audit log. Identify the scontext and tcontext in the denial message.
  • Run matchpathcon on several system files: /etc/passwd, /etc/shadow, /usr/sbin/httpd. Note the expected context for each and identify what process type would need that type of access.
RHCSA Objective

"List and identify SELinux file and process context." ls -Z (file context), ls -Zd (directory context), ps auxZ | grep SERVICE (process context), matchpathcon -V FILE (verify context is correct).