April 14th, 2011

10 things you probably did not know about SELinux.. #5

#5 How do I add new file systems/disks to an SELinux machine?

Lets examine three use cases:

1: You just got back from Best Buy with a brand new 100 Gig Disk that you want to mount on /home and store your homedirs.  You add the disk mount to /etc/fstab, mount it untar your entire backed up directory to the disk.  Now you attempt to login with a confined user.  Login fails, and the audit logs fill up with AVC messages concerning file_t.  Even without confined logins, applications like sshd can't read the ~/.ssh directory and Apache can no longer read the ~/public_html directory.

SELinux reporting errors with the type file_t indicates that the file/dir has no label.  SELinux has no idea what content is stored in a file without a label, therfore the kernel denies confined applications access to these files.  Ordinarily when I have seen random files all over the disk labelled file_t, I have told the user to relabel the entire machine.  touch /.autorelabel; reboot  In this case we know the user just added a disk, so all he needs to do is run restorecon on the disk.  restorecon -R -v /home.  The restorecon command will put the default labels on the entire disk.  This  also works on disks that you moved from one machine to another, especially important if the machine had SELinux disabled.

2. You add a new lvm mount that you want to store all of your postgresql database directory on.  You create a new directory tree /data/postgresqldb and mount the disk here and mount the directory on /data/pgsql.    You are an advanced SELinux user so you know you need to put labels down,  you run "restorecon -R -v /data/pgsql".   Now you service postgresql start, and POW it blows up.  The setroubleshoot star shows up and you read the analysys.  The analysys tells you that postgresql is trying to access a file in a directory labeled default_t.  Newly created directories in / are labelled default_t.  Just like file_t, the SELinux kernel does not know what content is stored in a file/directory labeled default_t, so all confined applications are blocked from reading default_t files/directories.  The setroubleshoot analysis also tells you you need to put a label on the directory, and choose from a list of labels including postgresql_db_t.  You figure that looks good and you follow the instructions,

# semanage fcontext -a -t postgresql_db_t '/data/pgsql(/.*)?'
# restorecon -R -v /data/pgsql

The semanage command tells the SELinux system what the default label for this directory will be going forward.  The restorecon command actually puts the labels on the disk.

Now you service postgresql start, and POW it blows up again.   At this point you are real unhappy with SELinux.  This time the AVC's indicate that postgresql_t is not able to search through the /data directory which is labelled default_t.  Your labelling was added at a directory a level below what you needed.

# semanage fcontext -d '/data/pgsql(/.*)?'
# semanage fcontext -a -t postgresql_db_t '/data(/.*)?'
# restorecon -R -v /data

I am sorry we blew it on this, but hopefully this example will help you understand a little of what SELinux is doing.

# service postgresql start

It works!!!

Now you can take the pins out of the voodoo doll of me.

NOTE:  If you were to store the postgresql database in a subdirectory of a normal file system directory, DO NOT change the label of that directory.
For example /home/postgesql. 

# semanage fcontext -a -t postgresql_db_t '/home(/.*)?'
# restorecon -R -v /home

Would thoroughly screw up your machine.  In this case it is better to do

# semanage fcontext -a -t postgresql_db_t '/home/pgsql(/.*)?'
# restorecon -R -v /home
Then add allow rules for posqgresql_t to search through home_root_t using

#grep postgresql_t /var/log/audit/audit.log | audit2allow -M mypostgresql
# semodule -i mypostgresql.pp
3. You want to share Apache data on an NFS share using multiple httpd hosts.   You mount the remove nfs directory at /var/www/.

# service httpd start
It blows up permission denied.  This time setroubleshoot is complaining about httpd_t trying to read nfs_t.  The analysis tells you that you can allow httpd_t to read all nfs_t by setting a couple of different booleans.

httpd_use_nfs or use_nfs_home_dirs

Since you are not using nfs for your  home directories, it would be a bad idea from a security point of view to turn this boolean on.  The use_nfs_home_dirs boolean allows any confined domains that need access to  home directory content to get access to all files labeled nfs_t.

Turning on httpd_use_nfs will solve your problem. 
But what if you had other nfs shares mounted which you did not want to grant access to Apache?

The third option would be to use a mount option. 

# mount -o context="system_u:object_r:httpd_sys_content_t:s0" REMOTEHOST:/var/www /var/www

This command tells the SELinux kernel to treat all content in this file system as httpd_sys_content_t.  httpd_t will be allowed to access the content  mounted as httpd_sys_content_t,  but the kernel will still deny httpd_t access to other NFS file systems mounted on the system.