File contexts: rules, restorecon and chcon
The most frequent SELinux problem in practice is a service that cannot read a directory you created, because the files have the wrong type. This lesson shows how a file gets its label, how to see what label it should have, and how to fix it so that the fix survives a relabel, a restore and a reboot.
- Explain how the policy's path rules decide the label of a file, and see the expected type with
matchpathcon. - Set a permanent label rule with
semanage fcontextand apply it withrestorecon. - Explain why
chconis only temporary, and whatcpandmvdo to a label.
The scenario
You install the Apache web server (dnf install httpd), put a page in a new directory /srv/web, and point DocumentRoot at it. The page is world-readable, yet:
[root@servera ~]# ls -Z /srv/web/index.html
unconfined_u:object_r:var_t:s0 /srv/web/index.html
[root@servera ~]# curl -s -o /dev/null -w "%{http_code}\n" http://localhost/
403The file is labelled var_t, because the policy has a rule that labels everything below /srv that way. The web server's process type httpd_t is not allowed to read var_t; it is allowed to read httpd_sys_content_t, which is the label of /var/www. Ask the policy what a path should have:
[root@servera ~]# matchpathcon /var/www/html/index.html /srv/web/index.html
/var/www/html/index.html system_u:object_r:httpd_sys_content_t:s0
/srv/web/index.html system_u:object_r:var_t:s0The permanent fix: a rule, then restorecon
Rules and labels: Step through making a custom directory labelled correctly, permanently.
[root@servera ~]# semanage fcontext -a -t httpd_sys_content_t "/srv/web(/.*)?"
[root@servera ~]# semanage fcontext -l | grep /srv/web
/srv/web(/.*)? all files system_u:object_r:httpd_sys_content_t:s0
[root@servera ~]# restorecon -Rv /srv/web
Relabeled /srv/web from unconfined_u:object_r:var_t:s0 to unconfined_u:object_r:httpd_sys_content_t:s0
Relabeled /srv/web/index.html from unconfined_u:object_r:var_t:s0 to unconfined_u:object_r:httpd_sys_content_t:s0
[root@servera ~]# curl -s -o /dev/null -w "%{http_code}\n" http://localhost/
200In the pattern "/srv/web(/.*)?", /srv/web is the directory and (/.*)? means "and optionally a slash followed by anything": the directory plus everything below it. Quote it, so the shell does not touch the special characters. semanage is in the package policycoreutils-python-utils.
Useful variations: semanage fcontext -l -C lists only your own rules, semanage fcontext -d "PATTERN" deletes one, and restorecon -Rnv PATH previews what a relabel would change without doing it. Files created in /srv/web from now on get the label automatically.
chcon: handy, but temporary
chcon sets a label directly on one file, with no rule behind it:
[root@servera ~]# chcon -t user_home_t /srv/web/copy.html
[root@servera ~]# ls -Z /srv/web/copy.html
unconfined_u:object_r:user_home_t:s0 /srv/web/copy.html
[root@servera ~]# restorecon -v /srv/web/copy.html
Relabeled /srv/web/copy.html from unconfined_u:object_r:user_home_t:s0 to unconfined_u:object_r:httpd_sys_content_t:s0The next restorecon, or a full relabel after an update or a reboot with /.autorelabel, puts the rule's label back. Use chcon to experiment; use semanage fcontext for the real fix.
cp versus mv
How a file arrives in the directory matters:
Copying versus moving: Select an operation to see which label the file ends up with.
[root@servera ~]# cp /tmp/second.html /srv/web/copy.html
[root@servera ~]# mv /tmp/moved.html /srv/web/moved.html
[root@servera ~]# ls -Z /srv/web/copy.html /srv/web/moved.html
unconfined_u:object_r:httpd_sys_content_t:s0 /srv/web/copy.html
unconfined_u:object_r:user_tmp_t:s0 /srv/web/moved.htmlThe copy is a new file and takes the label from the directory's rule; the moved file is the same file with its old user_tmp_t label, and the web server cannot read it. After moving files into a service directory, run restorecon -R on them.
Try it
Check your understanding
- You created /srv/web and httpd cannot read it. Which pair of commands fixes it permanently?
- Which command shows the type the policy expects for a path?
- A file moved with mv into a service directory is not served. Why?
- What does restorecon -Rnv /srv do?
- Why is chcon not a permanent fix?
- What does the pattern /srv/web(/.*)? match?