RED HAT ENTERPRISE LINUX
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
- 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
-
List SELinux contexts for files and directories —
Use
ls -Zandls -lZto display security contexts for files, directories, and symlinks -
List SELinux contexts for processes —
Use
ps -Zandps auxZto display the security context of running processes -
Identify expected contexts and diagnose mismatches —
Use
matchpathcon,semanage fcontext -l, andausearchto 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 |
|---|---|---|---|
| User | 1st | SELinux user identity — maps to Linux users | system_u, unconfined_u |
| Role | 2nd | SELinux role — determines allowed types | object_r (files), system_r (processes) |
| Type | 3rd | The primary policy decision point — what can access what | httpd_t, httpd_sys_content_t, sshd_t |
| Level | 4th | MLS/MCS sensitivity level — usually s0 on targeted systems | s0, s0:c0,c1 |
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_t | Apache web server (httpd_t) |
/etc/httpd/ | httpd_config_t | Apache configuration |
/var/log/httpd/ | httpd_log_t | Apache log files |
/etc/ssh/ | etc_t, sshd_key_t | SSH server config and keys |
/var/log/ | var_log_t | System logging daemons |
/home/user/ | user_home_t | User's own files |
/tmp/ | tmp_t | All processes (temporary files) |
/etc/ | etc_t | System configuration |
/usr/sbin/httpd | httpd_exec_t | Entry point for httpd_t domain |
/var/lib/mysql/ | mysqld_db_t | MariaDB/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 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 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 FILE | File context(s) | Check what context a file currently has |
ls -Zd DIR | Directory's own context | Check the context of a directory itself |
ps -Z | Process contexts (current user's processes) | See what domain a process is running in |
ps auxZ | All process contexts | Find the context of any running service |
id -Z | Current user's context | Confirm the current shell's SELinux context |
matchpathcon PATH | Expected context from policy | Find out what context a path should have |
matchpathcon -V FILE | Actual vs expected context comparison | Verify if a file's context is correct |
semanage fcontext -l | All file context rules in the policy | Browse the complete context database |
ausearch -m AVC -ts recent | Recent SELinux denials | Find what SELinux denied and the contexts involved |
Context Identification Quick Reference
| Task | Command |
|---|---|
| Show file context | ls -Z /path/to/file |
| Show file context (long format) | ls -lZ /path/to/file |
| Show directory's own context | ls -Zd /path/to/dir |
| Show all files including hidden | ls -laZ /path/ |
| Show all process contexts | ps auxZ |
| Show context of a specific process | ps auxZ | grep PROCESSNAME |
| Show current user's context | id -Z |
| Find expected context for a path | matchpathcon /path/to/file |
| Verify file's context vs policy | matchpathcon -V /path/to/file |
| Search policy context database | sudo semanage fcontext -l | grep PATTERN |
| View recent SELinux denials | sudo ausearch -m AVC -ts recent |
| View human-readable denial explanations | sudo 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.
- 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. - Write the command to display the SELinux context of the file
/etc/ssh/sshd_config. - Write the command to display the SELinux context of the
/var/www/htmldirectory itself (not its contents). What is the difference from the command without the-dflag? - Write the command to show the SELinux context of all running httpd processes.
- A file at
/var/www/html/page.htmlwas 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. - In an AVC denial message, what do
scontextandtcontextrepresent, and which one usually needs to be fixed?
Knowledge Check — Answers
- 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. ls -Z /etc/ssh/sshd_configls -Zd /var/www/html— the-dflag shows the context of the directory entry itself. Without-d,ls -Z /var/www/htmlshows the contexts of the files and subdirectories inside the directory, not the directory's own context.ps auxZ | grep httpd- (a)
ls -Z /var/www/html/page.html— shows the actual current context (will showuser_home_t).
(b)matchpathcon -V /var/www/html/page.html— compares actual context to the expected policy context, showing the mismatch. 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 usingrestorecon.
Key Takeaways
-
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). -
Use the
-Zflag 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. -
matchpathcon -V FILEconfirms whether a context is correct. "verified" = context matches the policy. Any other output = mismatch.semanage fcontext -l | grep PATTERNshows all rules for a path pattern. Use both to diagnose wrong-context problems. -
mvpreserves context; files moved from home dirs have wrong context. AVC denials show:scontext= the process (usually correct);tcontext= the file (usually needs fixing withrestorecon). Useausearch -m AVC -ts recentto find denials.
Graded Lab
- Run
ls -Z /var/www/html/to view the contexts of web content files. Runls -Zd /var/www/htmlto view the directory's own context. Confirm both showhttpd_sys_content_t. - Run
ps auxZ | grep httpdto view the context of the Apache process. Identify the domain (httpd_t). Runps auxZ | grep sshdto see the sshd context. Runid -Zto see your own context (unconfined_t). - Create a test file in your home directory:
touch ~/test.html. Check its context withls -Z ~/test.html— it should showuser_home_t. Move it to/var/www/html/. Check the context again — confirm it still showsuser_home_t. - Run
matchpathcon -V /var/www/html/test.htmlto confirm the mismatch. Observe the "has context" vs "should be" output. Runsudo semanage fcontext -l | grep "/var/www/html"to see the policy rule for that directory. - Use
sudo ausearch -m AVC -ts recentto 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
matchpathconon 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.
"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).