Restore Default
File Contexts

Restore default file contexts

CIS126RH | RHEL System Administration 1
Mesa Community College

When a file has the wrong SELinux context — because it was moved from another location, created by an unconfined process, or accidentally relabeled — services that depend on it will be denied access even if Unix permissions are correct. The fix is restorecon, which resets a file's context to the default defined by the SELinux policy. For custom directories not covered by policy, semanage fcontext adds a new rule first, then restorecon applies it. Both workflows are tested on the RHCSA exam.

Learning Objectives

  1. Explain why file contexts become incorrect — Describe the three common causes of context mismatches and why restorecon fixes them
  2. Restore contexts with restorecon — Use restorecon to reset a file or directory tree to the default context defined in the SELinux policy
  3. Add custom context rules with semanage fcontext — Use semanage fcontext -a to define the correct context for a custom directory path, then apply it with restorecon
  4. Verify context restoration and use chcon for temporary changes — Confirm contexts are correct after restoration and understand when chcon is appropriate versus restorecon

Why File Contexts Become Wrong

Three common causes of SELinux context mismatches — each has a specific fix.

Cause How it happens Fix
File moved with mv mv preserves the original file's SELinux context — the file arrives at the new location with the old type restorecon resets the context to match the new location's policy rule
File in a custom directory The directory path has no rule in the SELinux policy — files inherit a generic type semanage fcontext -a to add the rule, then restorecon to apply it
Context changed with chcon chcon sets a temporary context that does not survive restorecon or relabel restorecon resets to the policy-defined context (undoing the chcon)
restorecon reads the policy; it does not guess

restorecon queries the SELinux policy database (the same database matchpathcon reads) to find the correct context for a file path, then applies it. If the path has no policy rule, the context is unchanged.

restorecon: Resetting to Policy Defaults

restorecon resets a file's SELinux context to the default defined in the policy for that file path.

# Restore context of a single file
$ sudo restorecon /var/www/html/page.html

# -v flag: verbose — shows what changed
$ sudo restorecon -v /var/www/html/page.html
Relabeled /var/www/html/page.html
  from unconfined_u:object_r:user_home_t:s0
  to   system_u:object_r:httpd_sys_content_t:s0

# Restore context of a directory and all its contents recursively
$ sudo restorecon -Rv /var/www/html/
Relabeled /var/www/html/page.html from user_home_t to httpd_sys_content_t
Relabeled /var/www/html/images/photo.jpg from user_home_t to httpd_sys_content_t

# -n flag: dry run — show what would change without changing it
$ sudo restorecon -Rvn /var/www/html/
Would relabel /var/www/html/page.html from user_home_t to httpd_sys_content_t
RHCSA exam pattern: restorecon -Rv

For any task involving web content, service files, or moved files with wrong contexts, the fix is sudo restorecon -Rv /path/to/directory/. The -R flag handles all files recursively; -v confirms what was changed.

restorecon Flags Reference

Flag Purpose When to use
-vVerbose — show what context changes were madeAlways — confirms the fix worked and shows before/after
-RRecursive — process a directory and all contentsWhen multiple files in a directory need relabeling
-nDry run — show what would change without making changesPreview before applying; verify the fix is correct
-FForce — reset context even if it appears correctWhen a context looks right but still causing issues
-e DIRExclude — skip a subdirectory during recursive relabelingWhen a subdirectory needs to keep its current context
# Most common exam usage patterns
$ sudo restorecon -v  FILE          # single file, verbose
$ sudo restorecon -Rv DIRECTORY/   # recursive + verbose
$ sudo restorecon -Rvn DIRECTORY/  # dry run first, then remove -n

The Standard restorecon Workflow

Exam scenario: web content was moved from a home directory to /var/www/html/. Apache cannot serve it. Fix the context.

# Step 1: Confirm the wrong context
$ ls -Z /var/www/html/page.html
unconfined_u:object_r:user_home_t:s0 /var/www/html/page.html

# Step 2: Verify with matchpathcon
$ matchpathcon -V /var/www/html/page.html
has context user_home_t, should be httpd_sys_content_t

# Step 3: Restore the context
$ sudo restorecon -v /var/www/html/page.html
Relabeled /var/www/html/page.html
  from unconfined_u:object_r:user_home_t:s0
  to   system_u:object_r:httpd_sys_content_t:s0

# Step 4: Verify the fix
$ ls -Z /var/www/html/page.html
system_u:object_r:httpd_sys_content_t:s0 /var/www/html/page.html

$ matchpathcon -V /var/www/html/page.html
/var/www/html/page.html verified.   ← ✓ context is correct

semanage fcontext: Custom Context Rules

When content is served from a non-standard directory that the policy does not know about, add a new rule first, then apply it with restorecon.

# Scenario: web content stored at /webdata/ instead of /var/www/html/
$ ls -Zd /webdata
unconfined_u:object_r:default_t:s0 /webdata
# default_t — no specific policy rule exists for /webdata

# Step 1: Add a policy rule to /etc/selinux/targeted/contexts/files/
$ sudo semanage fcontext -a -t httpd_sys_content_t "/webdata(/.*)?"
# -a = add rule, -t = type, regex covers dir and all contents

# Step 2: Confirm the rule was added
$ sudo semanage fcontext -l -C
SELinux fcontext               type            Context
/webdata(/.*)?                 all files       system_u:object_r:httpd_sys_content_t:s0

# Step 3: Apply the rule to existing files
$ sudo restorecon -Rv /webdata/
Relabeled /webdata from default_t to httpd_sys_content_t
Relabeled /webdata/index.html from default_t to httpd_sys_content_t

# Step 4: Verify
$ ls -Zd /webdata
system_u:object_r:httpd_sys_content_t:s0 /webdata

semanage fcontext Syntax Reference

# Add a rule: semanage fcontext -a -t TYPE "PATTERN"
$ sudo semanage fcontext -a -t httpd_sys_content_t "/webdata(/.*)?"

# The regex pattern: "/webdata(/.*)?"
# /webdata       = matches the directory itself
# (/.*)?         = matches anything inside the directory (optional)
# The ? makes the inner group optional → covers both dir and contents

# Modify an existing custom rule
$ sudo semanage fcontext -m -t httpd_sys_rw_content_t "/webdata(/.*)?"

# Delete a custom rule
$ sudo semanage fcontext -d "/webdata(/.*)?"

# List all rules (built-in + custom)
$ sudo semanage fcontext -l | grep webdata

# List only custom rules (administrator-added)
$ sudo semanage fcontext -l -C

# Copy context rules from an existing path (convenient shortcut)
$ sudo semanage fcontext -a -e /var/www/html /webdata
# -e = equivalent to: copy all context rules from /var/www/html to /webdata

chcon: Temporary Context Changes

chcon changes a file's SELinux context directly — but the change is temporary and will be overwritten by restorecon or a filesystem relabel.

# chcon sets context directly on a file (temporary)
$ sudo chcon -t httpd_sys_content_t /webdata/index.html

# chcon with -R for recursive
$ sudo chcon -Rt httpd_sys_content_t /webdata/

# Copy context from a reference file
$ sudo chcon --reference /var/www/html/index.html /webdata/index.html

# Problem: chcon changes are NOT persistent
# If restorecon or relabel runs later, the chcon change is overwritten
$ sudo restorecon -v /webdata/index.html
Relabeled /webdata/index.html
  from httpd_sys_content_t   ← the chcon change
  to   default_t             ← back to what the policy says (no rule = default_t)
chcon is temporary — use semanage fcontext + restorecon instead

chcon is useful for quick testing, but should never be the final fix. For persistent context changes, always use semanage fcontext -a (to add the policy rule) followed by restorecon (to apply the rule).

Choosing the Right Tool

The decision between restorecon alone and semanage fcontext + restorecon depends on whether the file path already has a policy rule.

Scenario Policy rule exists? Fix
File moved from home dir to /var/www/html/ Yes — /var/www/html is covered sudo restorecon -Rv /var/www/html/
File accidentally relabeled with chcon Yes — original path has a rule sudo restorecon -v FILE
Web content in /webdata/ (custom path) No — new path, no rule semanage fcontext -a -t TYPE "/webdata(/.*)?" then restorecon -Rv /webdata/
Test whether a context fixes access (quick) Either chcon -t TYPE FILE — test only, then use semanage for permanent fix
Entire filesystem has wrong contexts (after re-enable from disabled) All paths touch /.autorelabel and reboot — full relabel at boot

Practical Scenario: Custom Apache Document Root

Exam scenario: configure Apache to serve content from /srv/webdata/ and ensure SELinux allows access.

# Step 1: Create the custom document root and add content
$ sudo mkdir -p /srv/webdata
$ echo "Test page" | sudo tee /srv/webdata/index.html

# Step 2: Check the current context
$ ls -Zd /srv/webdata
unconfined_u:object_r:var_t:s0 /srv/webdata
# var_t is not accessible by httpd_t — Apache will be denied

# Step 3: Add the context rule for the custom path
$ sudo semanage fcontext -a -t httpd_sys_content_t "/srv/webdata(/.*)?"

# Step 4: Apply the rule
$ sudo restorecon -Rv /srv/webdata/
Relabeled /srv/webdata from var_t to httpd_sys_content_t
Relabeled /srv/webdata/index.html from var_t to httpd_sys_content_t

# Step 5: Verify
$ ls -Zd /srv/webdata
system_u:object_r:httpd_sys_content_t:s0 /srv/webdata
$ matchpathcon -V /srv/webdata/index.html
/srv/webdata/index.html verified.

Full Filesystem Relabeling: /.autorelabel

For mass context problems — or after re-enabling SELinux from disabled — the /.autorelabel file triggers a complete relabel at the next boot.

# Trigger a full filesystem relabel at next boot
$ sudo touch /.autorelabel
$ sudo reboot

# At boot: the system relabels every file, then reboots again normally
# This process can take several minutes on large filesystems

# When to use /.autorelabel:
# 1. Re-enabling SELinux after it was set to disabled
# 2. After modifying the SELinux policy significantly
# 3. When a large number of files have incorrect contexts
# 4. As a last resort when restorecon on individual paths is impractical

# After relabeling, check that key directories have correct contexts
$ ls -Zd /var/www/html /etc /home
system_u:object_r:httpd_sys_content_t:s0 /var/www/html
system_u:object_r:etc_t:s0               /etc
system_u:object_r:home_root_t:s0         /home

Context Restoration Quick Reference

Task Command
Restore context of a single filesudo restorecon -v FILE
Restore context recursivelysudo restorecon -Rv DIRECTORY/
Dry run (preview without changing)sudo restorecon -Rvn DIRECTORY/
Add a custom context rulesudo semanage fcontext -a -t TYPE "PATH_REGEX"
Standard regex for a directory + contents"/path/to/dir(/.*)?"
View custom rules onlysudo semanage fcontext -l -C
Modify a custom rulesudo semanage fcontext -m -t TYPE "PATH_REGEX"
Delete a custom rulesudo semanage fcontext -d "PATH_REGEX"
Copy rules from reference pathsudo semanage fcontext -a -e /ref/path /new/path
Temporary context change (test only)sudo chcon -t TYPE FILE
Full filesystem relabel at bootsudo touch /.autorelabel && sudo reboot
Verify context is correctmatchpathcon -V FILE

Common Mistakes

Mistake What goes wrong Correct approach
Using restorecon without first adding a rule for a custom path restorecon has no rule to apply — context stays as default_t or unchanged Run semanage fcontext -a -t TYPE "PATH(/.*)?" first, then restorecon -Rv
Using chcon as the permanent fix Context change is lost when restorecon or relabel runs later Use chcon only for testing; use semanage fcontext + restorecon for persistence
Forgetting the -R flag when relabeling a directory with multiple files Only the directory itself is relabeled — files inside remain with wrong context Always use restorecon -Rv DIRECTORY/ — include the trailing slash
Wrong regex pattern — missing the (/.*)? suffix Rule matches only the directory, not files inside it — files keep wrong context after restorecon Pattern must be "/path/to/dir(/.*)?" to cover both the directory and its contents
Not verifying after restorecon Context may not have changed if restorecon had no rule to apply Always verify with matchpathcon -V FILE or ls -Z FILE after restorecon
Using semanage fcontext but then not running restorecon The rule is saved but not yet applied to existing files — contexts still wrong semanage fcontext only adds the rule; restorecon -Rv PATH applies it to existing files

Comparing the Three Context Tools

Tool What it does Persistent? When to use
restorecon Resets context to what the policy database says for that path Yes — survives relabels because it reads the policy Standard path with a policy rule — file moved/copied/mislabeled
semanage fcontext Adds, modifies, or removes a file context rule in the policy database Yes — writes to the persistent policy store Custom path with no existing policy rule — must run restorecon after
chcon Sets context directly on the file (bypasses the policy database) No — overwritten by restorecon or relabel Quick testing only — confirm the correct type fixes the problem
# Testing workflow using chcon then making it permanent
# 1. Test with chcon (quick, temporary)
$ sudo chcon -t httpd_sys_content_t /srv/webdata/index.html
# 2. Confirm service works now
# 3. Make it permanent with semanage + restorecon
$ sudo semanage fcontext -a -t httpd_sys_content_t "/srv/webdata(/.*)?"
$ sudo restorecon -Rv /srv/webdata/

Complete semanage + restorecon Workflow

Exam scenario: serve web content from /opt/webfiles/. Set the correct SELinux context persistently.

# Step 1: Create directory and content
$ sudo mkdir -p /opt/webfiles
$ echo "<h1>Hello</h1>" | sudo tee /opt/webfiles/index.html

# Step 2: Check current (incorrect) context
$ ls -Zd /opt/webfiles
unconfined_u:object_r:usr_t:s0 /opt/webfiles

# Step 3: Add context rule (the permanent fix)
$ sudo semanage fcontext -a -t httpd_sys_content_t \
    "/opt/webfiles(/.*)?"

# Step 4: Apply rule to existing files
$ sudo restorecon -Rv /opt/webfiles/
Relabeled /opt/webfiles from usr_t to httpd_sys_content_t
Relabeled /opt/webfiles/index.html from usr_t to httpd_sys_content_t

# Step 5: Verify persistence — rule survives future restorecon runs
$ matchpathcon -V /opt/webfiles/index.html
/opt/webfiles/index.html verified.

$ sudo semanage fcontext -l -C
/opt/webfiles(/.*)?    all files    system_u:object_r:httpd_sys_content_t:s0

Knowledge Check

Answer these before moving to the next slide.

  1. A web developer moved report.html from their home directory to /var/www/html/. Apache cannot serve it. Write the command to fix the context.
  2. Web content is stored at /mysites/ — a custom directory not covered by the SELinux policy. Write the two commands to give it the correct web content context persistently.
  3. What is the correct regex pattern for a semanage fcontext rule that should cover both the directory /mysites and all files inside it?
  4. What does chcon do, and why should it not be used as the final fix for a context problem?
  5. After running sudo restorecon -Rv /mysites/, you check with ls -Zd /mysites and the context is still default_t. What is the likely cause, and what additional step is needed?
  6. Write the complete verification command to confirm that a file's context matches the policy — and what "verified" in the output means.

Knowledge Check — Answers

  1. sudo restorecon -v /var/www/html/report.html
    Or for the whole directory: sudo restorecon -Rv /var/www/html/
    This works because /var/www/html/ is a standard path with a policy rule (httpd_sys_content_t) — restorecon has the information it needs.
  2. (1) sudo semanage fcontext -a -t httpd_sys_content_t "/mysites(/.*)?"
    (2) sudo restorecon -Rv /mysites/
  3. "/mysites(/.*)?" — the (/.*)? suffix matches the directory itself (when the group is absent) and any file or subdirectory inside it (when the group matches). The ? makes the inner group optional.
  4. chcon changes the file's SELinux context directly, bypassing the policy database. It takes effect immediately but is not persistent — the change is overwritten the next time restorecon runs or a filesystem relabel occurs. Use it only for quick testing, then make the fix permanent with semanage fcontext + restorecon.
  5. The likely cause is that semanage fcontext was not run first — /mysites has no policy rule, so restorecon has nothing to apply and leaves the context unchanged (or resets to the generic type for that location). Fix: run sudo semanage fcontext -a -t httpd_sys_content_t "/mysites(/.*)?" and then sudo restorecon -Rv /mysites/ again.
  6. matchpathcon -V /path/to/file. "verified" means the file's actual SELinux context (from ls -Z) matches the context the policy expects for that path. Any other output shows the mismatch between the actual and expected contexts and means the context is still wrong.

Key Takeaways

  1. For standard paths: sudo restorecon -Rv /path/. restorecon reads the policy database and resets contexts to what the policy expects. Use -v to see what changed, -R for directories. Works for files moved with mv, accidentally relabeled with chcon, or copied without inheriting the correct context.
  2. For custom paths: semanage fcontext -a first, then restorecon. sudo semanage fcontext -a -t TYPE "/path(/.*)?" adds the policy rule. sudo restorecon -Rv /path/ applies it to existing files. Without the semanage step, restorecon has no rule and does nothing.
  3. The regex "/path(/.*)?" covers the directory and all contents. The (/.*)? suffix is mandatory — without it, only the directory itself is matched, not files inside it. Verify the rule with semanage fcontext -l -C (shows custom rules).
  4. chcon is temporary — semanage fcontext + restorecon is permanent. Use chcon only to test whether a context type fixes the problem. Always follow up with semanage fcontext + restorecon for persistence. Verify every fix with matchpathcon -V FILE — "verified" = correct.

Graded Lab

  • Create a file in your home directory: touch ~/webtest.html. Confirm it has user_home_t context. Move it to /var/www/html/. Confirm the wrong context persists. Run restorecon -v to fix it. Verify with matchpathcon -V.
  • Create the directory /opt/labweb/ and add an index.html file. Check its context — note the type for a path under /opt. Run restorecon -Rv /opt/labweb/ and observe that the context does not change to httpd_sys_content_t (no rule exists yet).
  • Add a semanage fcontext rule: sudo semanage fcontext -a -t httpd_sys_content_t "/opt/labweb(/.*)?". Verify the rule was saved with semanage fcontext -l -C. Then run restorecon -Rv /opt/labweb/ and observe that the context changes this time.
  • Use chcon -t user_home_t /opt/labweb/index.html to simulate a wrong context. Verify with ls -Z. Then run restorecon -v /opt/labweb/index.html and observe that it restores httpd_sys_content_t — proving restorecon overrides chcon.
  • Run matchpathcon -V /opt/labweb/index.html. Confirm "verified". Then run semanage fcontext -l -C to confirm your custom rule is saved in the persistent policy store.
  • Delete the custom rule with semanage fcontext -d "/opt/labweb(/.*)?". Confirm it is gone with semanage fcontext -l -C. Run restorecon -Rv /opt/labweb/ again — observe the context reverts to the generic type since the rule was removed.
RHCSA Objective

"Restore default file contexts." Standard path: restorecon -Rv /path/. Custom path: semanage fcontext -a -t TYPE "/path(/.*)?" then restorecon -Rv /path/. Verify: matchpathcon -V FILE.