1. SELinux is all about labeling
Every process and object on the machine has a label associated with it, if your files are not labeled correctly access might be denied.
If a file is mislabeled a confined application might not be allowed access to the mislabeled file. If an executable is mislabeled, it may not transition to the correct label when executing, causing access violations and potentially causing it to mislabel files it creates. Processes and objects on the machines have labels. If the labeling is correct everything should work. Sometimes an admin decides to change the default labeling on the system. If an admin wants to store apache web pages in a unusual location, /srv/myweb. The admin needs to tell SELinux that the files stored there need to be accessible to the web server process. He does this by setting the labeling correctly in the system. The apache process is allowed to access files labeled httpd_sys_content_t.
# semanage fcontext -a -t httpd_sys_content_t '/srv/myweb(/.*)?'
This command tells the SELinux datastore that the /src/myweb directory and all files under it should be labeled httpd_sys_content_t. Tools like restorecon and rpm read this datastore when they are labeling or relabeling files. Note, however that the semanage command will not change the actual labels on files on your machine. You still need to execute restorecon to fix the labels.
# restorecon -R /srv/myweb
restorecon reads the SELinux datastore to determine how files under /srv/myweb should be labeled and then fixes them.
# matchpathcon /srv/myweb
matchpathcon reads the SELinux datastore and prints the default label for the specified path
2. You have to tell SELinux about how a confined process is being run.
A confined process/application can be run in many different ways. You need to tell SELinux about how you are configuring the application to run, so SELinux will allow it the proper access. SELinux does not do this automatically, SELinux has builtin if/then/else rules called booleans that allow you to tweak the predefined rules to allow different access. If you set up you apache web server to talk to a mysql server, you need to set a boolean to tell SELinux this is ok. You can do this with the setsebool command.
# setsebool -P httpd_can_network_connect_db 1
Tools like system-config-selinux or getsebool -a will list all of the possible booleans. On the latest Fedora systems you can run SELinux error messages (avc) through audit2allow -w (audit2why). This checks to see if any boolean could be set to allow the access. setroubleshoot is also pretty good at diagnosing problems.
3. SELinux rules are evolving and applications are sometimes broken
General errors in policy or applications can cause SELInux access denials. Sometimes an application is just broken or the SELinux policy has never seen the confined application run the code path that it is running. While the application is working correctly, SELinux is denying it access. You can add custom policy to your system simply by piping the SELinux error messages through audit2allow. Say a new version of postgresql comes out that SELinux is mistakenly denying access to a resource which it should be allowed to access. You can use audit2allow to build a custom policy module that can be installed on your system to allow the access.
# grep postgresql /var/log/audit/audit.log | audit2allow -R -M mypostgresql
This command will generate a local policy module which will allow all accesses that are currently being denied..
# semodule -i mypostgresql.pp
This command installs the local policy modifications to your system. You probably want to report the SELinux errors to bugzilla or a mailing list so your local modifications can be added to the distribution's policy or upstream.