20.2 List and Identify SELinux File and Process Contexts

Key Takeaways

  • SELinux labels are user:role:type:level tuples; on targeted policy, the type field (for example httpd_sys_content_t) is what you read most often for access decisions.
  • List file contexts with ls -Z (and ls -Zd for directories); list process contexts with ps -Z or ps auxZ; show your own context with id -Z.
  • Match process type to file type: a confined domain such as httpd_t needs correctly typed content, logs, and ports—wrong type is a classic AVC denial cause.
  • Compare contexts on working vs broken paths (for example /var/www/html vs a custom DocumentRoot) to spot mislabels before changing modes or booleans.
  • Identification is a read-only skill: this section focuses on listing and recognizing labels; restoring and persistently fixing labels is Section 20.3.
Last updated: August 2026

20.2 List and Identify SELinux File and Process Contexts

Quick Answer: File labels: ls -Z / ls -Zd. Process labels: ps -Z or ps auxZ. Your login context: id -Z. Read the type field in user:role:type:level first—on RHEL’s targeted policy, type is usually the decision that matters for services.

Why context identification is an EX200 skill

Under Manage security, Red Hat expects you to list and identify SELinux file and process contexts. Tasks look like:

  • “Identify the SELinux context of /var/www/html.”
  • “Show the context of the httpd process.”
  • “Determine whether files under /srv/web have the correct type for a web server.”
  • “Report the SELinux user/role/type of the current shell.”

Before you run restorecon or change booleans, you must see what is labeled and what is running. Graders and real systems both reward correct reading of -Z output.

Anatomy of a context

A full SELinux security context looks like:

user:role:type:level
unconfined_u:object_r:httpd_sys_content_t:s0
system_u:system_r:httpd_t:s0
FieldTypical meaning on RHEL targeted
userSELinux user identity (unconfined_u, system_u, root_u, …)—not always the same as the Linux login name
roleRole in role-based access (object_r for files, system_r for many daemons, unconfined_r, …)
type (domain for processes)The critical field for most RHCSA work—e.g. httpd_sys_content_t, httpd_t, sshd_t, user_home_t
levelSensitivity/category (s0, sometimes s0:c0.c1023 with MCS)—often s0 on simple tasks

Mental model: Linux discretionary permissions (ugo/rwx) answer “who may open this as UID/GID?” SELinux answers “may this domain (process type) access this type (file type) for this class of operation?” Both must allow access.

On targeted policy (RHEL default), many admin shells run as unconfined domains with broad freedom, while network-facing daemons (httpd_t, sshd_t, named_t, …) are tightly confined. That is why a file you can cat as root may still be denied to Apache if the type is wrong.

List file and directory contexts: ls -Z

ls -Z /var/www/html
ls -Z /var/www/html/index.html
ls -Zd /var/www/html
ls -laZ /var/www/html
CommandUse
ls -Z pathShow SELinux context with names
ls -Zd dirContext of the directory itself (not only its children)
ls -laZCombine long listing (DAC mode, owner) with SELinux context
ls -ZR dirRecursive listing (noisy; use carefully)

Example patterns you should recognize:

system_u:object_r:httpd_sys_content_t:s0  /var/www/html
unconfined_u:object_r:user_home_t:s0      /home/alice/public_html
system_u:object_r:var_t:s0                /var/myservice   # often wrong for httpd content
system_u:object_r:etc_t:s0                /etc/httpd

Common web content types:

TypeTypical use
httpd_sys_content_tStatic content readable by httpd
httpd_sys_rw_content_tContent httpd may write
httpd_sys_script_exec_tExecutable scripts (CGI-style paths)
httpd_config_tApache configuration
httpd_log_tApache logs
httpd_var_run_tRuntime files under /run

Home and user types:

TypeTypical use
user_home_tNormal home content
user_home_dir_tThe home directory inode itself
ssh_home_t~/.ssh materials
admin_home_tRoot’s home content in many policies

Shared / custom data:

TypeNote
var_tGeneric /var default—often insufficient for httpd DocumentRoot
default_tGeneric default—frequently appears on new filesystems or poorly labeled mounts
nfs_t / relatedNetwork filesystem labels when applicable

When a task moves web content to /srv/www or /web, ls -Zd /srv/www often reveals default_t or var_t instead of httpd_sys_content_t—that identification drives the restore/label fix in Section 20.3.

matchpathcon and stat (optional identification helpers)

matchpathcon /var/www/html
matchpathcon /srv/web
stat -c '%n %C' /var/www/html/index.html

matchpathcon shows what the policy’s file context database thinks a path should be labeled. Compare that to ls -Z actual label to see drift. stat -c '%C' prints the context in a compact form.

List process contexts: ps -Z

ps -Z
ps -eZ | head
ps -eZ | grep httpd
ps auxZ | grep -E 'httpd|sshd|nginx'
ps -ZC httpd
CommandUse
ps -ZContexts for processes in the current view
ps -eZAll processes with SELinux context
ps -ZC nameProcesses by name with context
ps auxZUser-oriented listing plus context

Example process lines (simplified):

system_u:system_r:httpd_t:s0     ... httpd
system_u:system_r:sshd_t:s0      ... sshd
unconfined_u:unconfined_r:unconfined_t:s0 ... bash

Identify:

  1. Is the daemon confined? (httpd_t yes; unexpected unconfined_t for a service may mean it was started oddly.)
  2. Does the domain match the service you think is running?
  3. Are helper processes in related domains?
systemctl status httpd
ps -eZ | grep httpd

If httpd is not running, start it only if the task allows—identification of installed unit vs running domain are different checks.

Current user context: id -Z

id -Z
id -Z alice

Example:

unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023

id -Z shows the SELinux identity of your session (or another user when permitted). On RHEL, interactive admins are often unconfined, which explains why root can edit files that httpd cannot serve—DAC allows root, and SELinux does not confine that shell the same way as httpd_t.

Related tools:

secon          # if available, decode context components
prompt often shows context in specialized shells—not required

Putting it together: process type vs file type

Access problems almost always reduce to:

Process domain T_process wants operation O on object type T_file (and class file/dir/…).

Identification workflow:

# 1) What domain is the service?
ps -eZ | grep httpd

# 2) What type is the content path?
ls -Zd /srv/web
ls -Z /srv/web | head

# 3) What should the path be?
matchpathcon /srv/web

# 4) Mode still enforcing?
getenforce

If httpd_t is serving files labeled user_home_t or default_t, you have identified a context mismatch. Do not conclude “SELinux is broken”—conclude “labels do not match the service domain.”

Directory vs contents

ls -Zd /srv/web
ls -Z /srv/web

Sometimes the directory is correct but new files created by copy (cp without preserving context) inherit an unexpected type, or only the top directory was relabeled. Identify both directory and file labels.

Copy and create behavior (awareness)

cp /var/www/html/index.html /tmp/index.html
ls -Z /var/www/html/index.html /tmp/index.html

Copied files often receive a type based on the destination directory policy, not always a perfect clone of the source type—unless you use options that preserve contexts. Identification after copy is a common exam discovery step before restorecon.

Other useful listing commands

# Find files with a given type (can be slow on large trees)
sudo find /srv -context '*:httpd_sys_content_t:*' 2>/dev/null | head

# Show context with find -Z (GNU find on RHEL)
find /var/www -maxdepth 2 -Z 2>/dev/null | head

# Pathname regex rules (policy database)—advanced identification
sudo semanage fcontext -l | grep '/srv/web'

semanage fcontext -l lists persistent path → context rules. You do not need to memorize the full policy map, but grepping for a custom path shows whether a permanent mapping already exists. Changing those rules belongs with restore workflows (20.3); listing them is identification.

DAC vs MAC: do not misread ls -l

ls -laZ /srv/web/index.html

You might see:

-rw-r--r--. 1 root root ... unconfined_u:object_r:default_t:s0 index.html
  • Mode 644 and owner root may look “fine” for a web server reading world-readable files.
  • Type default_t may still cause AVC denial for httpd_t.

Always include -Z when SELinux is in play. Conversely, a perfect SELinux type with mode 000 still fails DAC.

Exam identification workflows

Workflow A — Web content path

getenforce
ls -Zd /var/www/html
ls -Z /var/www/html | head
matchpathcon /var/www/html
ps -eZ | grep httpd

Workflow B — Custom DocumentRoot

ls -Zd /srv/myapp
ls -Z /srv/myapp | head
matchpathcon /srv/myapp
sudo semanage fcontext -l | grep '/srv/myapp' || true

Workflow C — User home and SSH

ls -Zd /home/alice
ls -Za /home/alice/.ssh 2>/dev/null
id -Z alice
ps -eZ | grep sshd

Workflow D — Compare good vs bad

ls -Zd /var/www/html /srv/web
matchpathcon /var/www/html /srv/web

Side-by-side context comparison is the fastest way to see that /srv/web is mislabeled relative to a known-good path.

Workflow E — Process domain inventory

ps -eZ | awk '{print $1}' | sort | uniq -c | sort -nr | head

Shows which SELinux domains are active—useful when a task asks which domain a service uses.

Common traps

  1. Reading ls -l only and missing a wrong type.
  2. Checking files but not the directory (ls -Zd).
  3. Confusing SELinux user (unconfined_u) with Linux user (alice).
  4. Assuming root shell context means Apache can read the same path.
  5. Ignoring matchpathcon when actual ls -Z differs from expected policy.
  6. Looking at Permissive denials without identifying the process domain and file type pair.
  7. Treating default_t as “fine because world-readable.”
  8. Expecting id -Z alone to show file contexts—it shows identity, not path labels.
  9. Stopping at process list without ps -Z, so you never see httpd_t.
  10. Jumping to setenforce 0 before identifying the mismatch (mode change hides the teaching of labels).

Relationship to other sections

SkillSection
Enforcing/Permissive modes20.1
List/identify contexts20.2 (this)
restorecon / persistent fcontext20.3
Port types for non-default ports21.1
Booleans that loosen policy21.2

Identification tells you what is wrong; 20.3 and Chapter 21 tell you how to fix it without disabling SELinux.

Section checkpoint

You should list file contexts with ls -Z / ls -Zd, list process contexts with ps -Z / ps -eZ, show session context with id -Z, interpret user:role:type:level with emphasis on type/domain, compare actual labels to matchpathcon, relate httpd_t (and other domains) to content types such as httpd_sys_content_t, and separate DAC mode bits from SELinux labels. That is the EX200 skill to list and identify SELinux file and process contexts on RHEL 10.

Test Your Knowledge

Which command best lists the SELinux security context of files in a directory?

A
B
C
D
Test Your Knowledge

You need to see the SELinux domain of running httpd processes. Which approach is appropriate?

A
B
C
D
Test Your Knowledge

In the context unconfined_u:object_r:httpd_sys_content_t:s0, which field is usually most important for targeted-policy access decisions on RHEL?

A
B
C
D
Test Your Knowledge

What does id -Z display?

A
B
C
D