RED HAT ENTERPRISE LINUX
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
-
Explain why file contexts become incorrect —
Describe the three common causes of context mismatches and why
restoreconfixes them -
Restore contexts with restorecon —
Use
restoreconto reset a file or directory tree to the default context defined in the SELinux policy -
Add custom context rules with semanage fcontext —
Use
semanage fcontext -ato define the correct context for a custom directory path, then apply it withrestorecon -
Verify context restoration and use chcon for temporary changes —
Confirm contexts are correct after restoration and understand when
chconis appropriate versusrestorecon
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 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
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 |
|---|---|---|
-v | Verbose — show what context changes were made | Always — confirms the fix worked and shows before/after |
-R | Recursive — process a directory and all contents | When multiple files in a directory need relabeling |
-n | Dry run — show what would change without making changes | Preview before applying; verify the fix is correct |
-F | Force — reset context even if it appears correct | When a context looks right but still causing issues |
-e DIR | Exclude — skip a subdirectory during recursive relabeling | When 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 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 file | sudo restorecon -v FILE |
| Restore context recursively | sudo restorecon -Rv DIRECTORY/ |
| Dry run (preview without changing) | sudo restorecon -Rvn DIRECTORY/ |
| Add a custom context rule | sudo semanage fcontext -a -t TYPE "PATH_REGEX" |
| Standard regex for a directory + contents | "/path/to/dir(/.*)?" |
| View custom rules only | sudo semanage fcontext -l -C |
| Modify a custom rule | sudo semanage fcontext -m -t TYPE "PATH_REGEX" |
| Delete a custom rule | sudo semanage fcontext -d "PATH_REGEX" |
| Copy rules from reference path | sudo semanage fcontext -a -e /ref/path /new/path |
| Temporary context change (test only) | sudo chcon -t TYPE FILE |
| Full filesystem relabel at boot | sudo touch /.autorelabel && sudo reboot |
| Verify context is correct | matchpathcon -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.
- A web developer moved
report.htmlfrom their home directory to/var/www/html/. Apache cannot serve it. Write the command to fix the context. - 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. - What is the correct regex pattern for a
semanage fcontextrule that should cover both the directory/mysitesand all files inside it? - What does
chcondo, and why should it not be used as the final fix for a context problem? - After running
sudo restorecon -Rv /mysites/, you check withls -Zd /mysitesand the context is stilldefault_t. What is the likely cause, and what additional step is needed? - 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
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.- (1)
sudo semanage fcontext -a -t httpd_sys_content_t "/mysites(/.*)?"
(2)sudo restorecon -Rv /mysites/ "/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.chconchanges the file's SELinux context directly, bypassing the policy database. It takes effect immediately but is not persistent — the change is overwritten the next timerestoreconruns or a filesystem relabel occurs. Use it only for quick testing, then make the fix permanent withsemanage fcontext + restorecon.- The likely cause is that
semanage fcontextwas not run first —/mysiteshas no policy rule, sorestoreconhas nothing to apply and leaves the context unchanged (or resets to the generic type for that location). Fix: runsudo semanage fcontext -a -t httpd_sys_content_t "/mysites(/.*)?"and thensudo restorecon -Rv /mysites/again. matchpathcon -V /path/to/file. "verified" means the file's actual SELinux context (fromls -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
-
For standard paths:
sudo restorecon -Rv /path/. restorecon reads the policy database and resets contexts to what the policy expects. Use-vto see what changed,-Rfor directories. Works for files moved with mv, accidentally relabeled with chcon, or copied without inheriting the correct context. -
For custom paths:
semanage fcontext -afirst, thenrestorecon.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. -
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 withsemanage fcontext -l -C(shows custom rules). -
chcon is temporary — semanage fcontext + restorecon is permanent.
Use
chcononly to test whether a context type fixes the problem. Always follow up withsemanage fcontext + restoreconfor persistence. Verify every fix withmatchpathcon -V FILE— "verified" = correct.
Graded Lab
- Create a file in your home directory:
touch ~/webtest.html. Confirm it hasuser_home_tcontext. Move it to/var/www/html/. Confirm the wrong context persists. Runrestorecon -vto fix it. Verify withmatchpathcon -V. - Create the directory
/opt/labweb/and add anindex.htmlfile. Check its context — note the type for a path under/opt. Runrestorecon -Rv /opt/labweb/and observe that the context does not change tohttpd_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 withsemanage fcontext -l -C. Then runrestorecon -Rv /opt/labweb/and observe that the context changes this time. - Use
chcon -t user_home_t /opt/labweb/index.htmlto simulate a wrong context. Verify withls -Z. Then runrestorecon -v /opt/labweb/index.htmland observe that it restoreshttpd_sys_content_t— proving restorecon overrides chcon. - Run
matchpathcon -V /opt/labweb/index.html. Confirm "verified". Then runsemanage fcontext -l -Cto 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 withsemanage fcontext -l -C. Runrestorecon -Rv /opt/labweb/again — observe the context reverts to the generic type since the rule was removed.
"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.