Skip to content

Intermediate · SELinux and SSH · topic 30 of 57 · 35 min

Contexts and file labels: ls -Z, semanage fcontext and restorecon

Explanation

Every file and process has an SELinux context: user:role:type:level. The type (ending in _t) is what matters most. ls -Z and ps -Z show contexts. To label a custom folder correctly and permanently, add a rule with semanage fcontext -a and apply it with restorecon -Rv.

Reading a context

bash
$ ls -Z /var/www/html/index.html
unconfined_u:object_r:httpd_sys_content_t:s0 /var/www/html/index.html
$ ls -Zd /home/asha
unconfined_u:object_r:user_home_dir_t:s0 /home/asha
$ ps -eZ | grep httpd | head -1
system_u:system_r:httpd_t:s0      1301 ?        00:00:00 httpd
$ id -Z
unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023

A context has four parts separated by colons: SELinux user (system_u), role (object_r for files), type (httpd_sys_content_t), and level (s0, used for multi-level security). In the targeted policy, decisions are made almost entirely on the TYPE. So when people say "the label is wrong", they usually mean the type.

Where do file labels come from?

The policy contains a database of rules that map paths to types: /var/www(/.*)? should be httpd_sys_content_t, /home/[^/]+ should be user_home_dir_t, and so on. New files normally inherit the type of the directory they are created in. restorecon resets files to what the database says.

The classic problem: content in a custom folder

bash
# mkdir /web
# echo "Namaste" > /web/index.html
# ls -Z /web/index.html
unconfined_u:object_r:default_t:s0 /web/index.html
# (DocumentRoot set to /web in httpd.conf, httpd restarted)
$ curl http://localhost/
<title>403 Forbidden</title>
Normal permissions are fine (644), but default_t is not a type httpd_t may read.

The right fix: semanage fcontext + restorecon

bash
# semanage fcontext -a -t httpd_sys_content_t '/web(/.*)?'
# restorecon -Rv /web
Relabeled /web from unconfined_u:object_r:default_t:s0 to unconfined_u:object_r:httpd_sys_content_t:s0
Relabeled /web/index.html from unconfined_u:object_r:default_t:s0 to unconfined_u:object_r:httpd_sys_content_t:s0
$ curl http://localhost/
Namaste
semanage adds a permanent rule to the database; restorecon applies it. '/web(/.*)?' means /web itself and everything under it.

semanage comes from the policycoreutils-python-utils package. Find the type you need by looking at the default location: ls -Zd /var/www/html shows httpd_sys_content_t. semanage fcontext -l | grep /var/www lists the existing rules for that path. Use httpd_sys_rw_content_t if the web app must WRITE there (uploads).

chcon: temporary only

chcon -t httpd_sys_content_t /web/index.html also changes a label, but it does not touch the database. The next restorecon, or a full relabel, puts the old label back. Use chcon only for a quick test; always finish with semanage fcontext.

Copy versus move

ActionLabel of the result
cp file /var/www/html/New file: inherits the target directory's type (good)
mv file /var/www/html/Keeps its OLD label (often wrong, e.g. user_home_t)
cp -a or cp --preserve=contextKeeps the old label

A very common real-world bug: a developer builds a page in their home directory and mv's it into /var/www/html. It keeps user_home_t, and httpd gets "403 Forbidden". restorecon -Rv /var/www/html fixes it.

Common mistakes

  • Using chcon and thinking it is permanent.
  • Writing the semanage pattern without quotes, or as /web/* instead of '/web(/.*)?'. The pattern is a regular expression.
  • Running semanage fcontext and forgetting restorecon. The rule exists but existing files keep their old label.
  • Changing normal permissions to 777 to fix an SELinux denial. It does not help and adds a new hole.

Need help?

Stuck on a word or an idea? Search this course, or every course, and jump straight to the explanation or a worked question.

Try:

Watch the lesson

Contexts and file labels: ls -Z, semanage fcontext and restorecon · 1/6

user:role:type:level

Every file and process has a context: user, role, type and level. The type matters most.

Prefer a video by a teacher? Find free videos on “selinux semanage fcontext restorecon httpd tutorial” on YouTube ↗

In real life: Moving a government portal's files to a new disk

A state government portal moved its web files to a new, bigger disk mounted on /srv/portal. After the move, every page showed 403 Forbidden. The new file system had default_t labels. The admin added one semanage fcontext rule for /srv/portal, ran restorecon, and the portal was back in two minutes, with SELinux still enforcing.

bash
# semanage fcontext -a -t httpd_sys_content_t '/srv/portal(/.*)?'
# restorecon -R /srv/portal
# ls -Zd /srv/portal
system_u:object_r:httpd_sys_content_t:s0 /srv/portal

Practice (0/4 done)

Task 1 · Question

In system_u:object_r:httpd_sys_content_t:s0, which part is the type?

Task 2 · Code · Python

Write parse_context(ctx) that splits an SELinux context like "system_u:object_r:httpd_sys_content_t:s0" into a dict with keys user, role, type and level. The level itself may contain colons (for example "s0-s0:c0.c1023"), so only split on the first three colons.

Task 3 · Question

Which line has the bug? Goal: label /data/www permanently for httpd. 1: semanage fcontext -a -t httpd_sys_content_t '/data/www(/.*)?' 2: chcon -R -t default_t /data/www 3: restorecon -Rv /data/www

Task 4 · Practice

Serve a page from /web with httpd while SELinux stays enforcing: set DocumentRoot (and its <Directory>) to /web, see the 403, then fix the label permanently.

Quick quiz

Question 1

1.Which command applies the labels from the policy database to existing files?

Question 2

2.Why is chcon not a permanent fix?

Question 3

3.A file moved with mv from /home/asha to /var/www/html gives 403. Why?

Question 4

4.Which package provides semanage on RHEL 9?

Question 5

5.Which type should a folder where the web app saves uploads have?

Read more (free)

Open a question to see the answer and why. The first ones are this topic's own quiz, so try the quiz above before you peek.

Which command applies the labels from the policy database to existing files?

Answer: restorecon

restorecon resets labels to the database values.

Why is chcon not a permanent fix?

Answer: The next restorecon or relabel resets the label

chcon does not change the database.

A file moved with mv from /home/asha to /var/www/html gives 403. Why?

Answer: mv keeps the old user_home_t label

Moved files keep their context; run restorecon.

Which package provides semanage on RHEL 9?

Answer: policycoreutils-python-utils

dnf provides semanage tells you.

Which type should a folder where the web app saves uploads have?

Answer: httpd_sys_rw_content_t

The rw type allows httpd to write.

A port already has a different label. Which semanage option changes it?Related

Answer: -m

-m modifies an existing record.

From SELinux booleans and port labels

What does SELinux add to normal Linux permissions?Related

Answer: Mandatory, label-based rules that even root processes must follow

It is mandatory access control based on labels.

From SELinux: what it is and its modes

Which command shows SELinux denials from the last few minutes?Related

Answer: ausearch -m AVC -ts recent

ausearch filters audit records by type and time.

From Troubleshooting SELinux denials

Which command copies the folder /etc/ssh with all owners and permissions kept?Related

Answer: cp -a /etc/ssh /backup

-a (archive) copies recursively and keeps owner, permissions and times.

From Working with files: ls, cp, mv, rm, links and find

Pass the quiz (60% or more) or mark this topic as done when you are ready.

Your progress is saved on this device only.

Next steps

  1. 3 more topics in “SELinux and SSH” before its exam: SELinux booleans and port labels, Troubleshooting SELinux denials, SSH: keys, ssh-copy-id and hardening sshd.
  2. Module 6 exam: SELinux and SSH · 13 questions · 25 min, without help. 5 topics of this module still to finish first.
  3. Then the next module, Automation basics: scheduling, archives and shell scripts. 57 topics left in the course before the final exam.

← Previous: SELinux: what it is and its modes