I have a daemon (apache/samba/vsftpd/...) running on SELinux enabled system and I need to allow it to use files in a non-default location. The standard file permissions are configured to allow access.

If the daemon is running in permissive mode, everything works. When set back to enforcing it doesn't work anymore and I get a SELinux AVC denial messages.

How can I configure the system to allow the access in enforcing mode?


3 Answers 3



SELinux adds another layer of permission checks on Linux systems. On SELinux enabled systems regular DAC permissions are checked first, and if they permit access, SELinux policy is consulted. If SELinux policy denies access, a log entry is generated in audit log in /var/log/audit/audit.log or in dmesg if auditd isn't running on the system.

SELinux assigns a label, called security context, to every object (file, process, etc) in the system:

  • Files have security context stored in extended attributes. These can be viewed with ls -Z.

    SELinux maintains a database mapping paths patterns to default file contexts. This database is used when you need to restore default file contexts manually or when the system is relabeled. This database can be queried with semanage tool.

  • Processes are assigned a security context when an executable is run (execve syscall). Process security contexts can be viewed with most system monitoring tools, for example with ps Z $PID.

  • Other labeled objects also exist, but are not relevant to this answer.

SELinux policy contains the rules that specify which operations between contexts are allowed. SELinux operates on whitelist rules, anything not explicitly allowed by the policy is denied. The reference policy contains policy modules for many applications and it is usually the policy used by SELinux enabled distributions. This answer is primarily describing how to work with a policy based on the reference policy, which you are most likely using if you use the distribution provided policy.

When you run your application as your normal user, you probably do not notice SELinux, because default configuration places the users in unconfined context. Processes running in unconfined context have very few restrictions in place. You might be able to run your program without issues in user shell in unconfined context, but when launched using init system it might not work anymore in a restricted context.

Typical issues

When files are in a non-default location (not described in default policy) the issues are often related to the following reasons:

  • Files have incorrect/incompatible file context: Files moved with mv keep their metadata including file security contexts from old location. Files created in new location inherited the context from parent directory or creating process.

  • Having multiple daemons using the same files: The default policy does not include rules to allow the interaction between the security contexts in question.

Files with incorrect security context

If the files are not used by another daemon (or other confined process) and the only change is the location where files are stored, the required changes to SELinux configuration are:

  • Add a new rule to file context database
  • Apply correct file context to existing files

The file context on the default location can be used as template to for the new location. Most policy modules include man page documentation (generated using sepolicy manpages) explaining possible alternative file contexts with their access semantics.

File context database uses regualr expression syntax, which allows writing overlapping specifications. It is worthwhile to note that applied context is the last specification found [src].

To add a new entry to file context database:

semanage fcontext -a -t <type> "/path/here/(/.*)?"

After new context entry is added to the database, the context from database can be applied on your files using restorecon <files>. Running restorecon with -vn flags will show what file contexts would be changed without applying any changes.

Testing a new file context without adding a new entry in database

Context can be changed manually with chcon tool. This is useful when you want to test the new file context without adding an entry to file context database.

New file context is specified in the arguments to chcon. When used with --reference= option, the security context from a reference file is copied to the target files.

using a specific context (default_t):

chcon -t default_t <target files>

or using a reference:

chcon --reference=<path to default location> <target files>

Note about different file systems & mount points

If the new location is its own mount point, the context can be set with a mount option. Context set with mount option isn't stored on disk, so it can also be used with file systems that do not support extended attributes.

mount <device> <mount point> -o context="<context>"

Allowing processes running in different security contexts to use the same files

Option 1: Booleans

Reference policy includes tunable options, called booleans, which enable/disable certain additional rules. Many of them allow inter-operation of different system daemons which usually do not use same files.

List of all possible tunable options and their descriptions can be listed using semanage boolean -l. audit2allow might also be able to directly tell which boolean needs to be enabled.

To enable/disable a boolean using semanage:

semanage boolean --on <boolean name>
semanage boolean --off <boolean name>

Booleans are the simplest way to modify the policy. However, all possible situations can not be addressed by toggling a boolean. Some booleans also allow very broad access, being overly permissive.

Option 2: Extend policy with a new module

If no boolean exists to allow the access, the policy needs to be modified by adding a custom module.

A simple module adding the required rules to allow access can be generated from log files using audit2allow with following steps:

  1. Set the daemon's domain (security context) to permissive mode. In permissive mode the policy isn't enforced, but logs are generated on the access the policy would normally deny.

    semanage permissive -a <domain>
  2. Test your daemon in normal operation to generate log entries.

  3. Create a new policy module and insert it.

    audit2allow -a -M <name>
    semodule -i <name>.pp'
  4. Re-enable enforcing mode

    semanage permissive -d <domain>

This method works best when there are only a few security contexts involved. In a complex configuration you quite likely have to write your own policy module. Some resources for getting started are gentoo wiki and the reference policy API documentation.


With this command:

# semanage fcontext -l /oldpath/

You can check the default SElinux contexts in the folders in your system, so with that command you can see the default context of that daemon folder.

So then you can check whatever SELinux contexts you should configure in the directory you want to move your content to.

Let's say that you see that your daemon folder has this context (it's apache context):

# semanage fcontext -l
/var/www(/.*)? all files system_u:object_r:httpd_sys_content_t:s0

Then you will apply these contexts to the new path like this (example with apache daemon default security context)

# semanage fcontext -a -t httpd_sys_content_t '/newpath(/.*)?'

After doing that, considering that your content is already in the new path, you should force everything beneath that path, to get that context:

# restorecon -RFvv /newpath

You can check if it worked, with this command:

# ls -Zd /newpath/

Remember that when you mv a directory or files, it maintains the security context When you cp a folder or directory, it will set the context to that of the parent.

If you need to check the manual pages for specific software, you can install the man pages with:

# yum install -y selinux-policy-devel

Don't forget to execute this command, to reindex the man db:

# mandb

Then you can run this one, and check all selinux man pages.

# man -k selinux

Suggestion, run this command before and after installing that package, to see the difference:

# man -k selinux | wc -l

Quick answer for the impatient on SELinux read/write permissions(comments added to the lins).

Getenforce # see current mode.
getsebool -a # find al boolean values
Sudo setenforce 0 # shut it down, but its back at reboot -NOT RECOMMENDED other than debug.

Permanent solution below.

Line 2 below will work but won't survive rename & restorecon (line 3 will survive such things).

 ls -dZ /var/www/html  # See SELinux context of 
 sudo chcon -R -t httpd_sys_content_t /var/www/html/website-document-root
 sudo semanage fcontext -a -t httpd_sys_content_t "/var/www/html(/.*)?" 

I have also done the following in the past to give apache write permission.

Selinux allow httpd read & write to /var/www/html/my-project.

sudo chcon -R -t httpd_sys_script_rw_t /var/www/html/my-project/
sudo chcon -R -t httpd_sys_script_rw_t /var/www/my-Symfony-project/var/log/

SELinux references:


Not gonna repeat the talk about content or context -see above answers or link above (after all this is for the impatient)):

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .