The script se-file-context.sh sets the SELinux context for ePages applications:

. /etc/default/epages6
# /var/epages/se-file-context.sh -?
Usage:
  se-file-context.sh { --set | --restore } [ --perl-cgi ] [ --verbose ]
Options:
  --set     : set ePages SELinux context for web adapter files
  --restore: set default SELinux context for web adapter files
  --perl-cgi: set additionally SELinux context for Perl files
  --verbose: verbose output

se-file-context.sh is executed by /etc/init.d/epages6 whenever starting an ePages application if the envoronment variable EPAGES_ENABLE_SELINUX is set in /etc/default/epages6.

se-file-context.sh does nothing if:

  • the command chcon isn’t found (SELinux isn’t installed on the system at all)

  • the command getenforce does not return enforcing (SELinux isn’t switched on)

  • the user who executes the command isn’t root

se-file-context.sh --set

se-file-context.sh --set sets the SELinux context so that the MySQL server and the web server work together with ePages.

If epages-mysqld is installed, following parameters are set:

  • chcon -t texrel_shlib_t /etc/init.d/mysql (see EPG-15111)

  • chcon -t mysqld_db_t /var/lib/mysql (if it is a symlink, see EPG-15762)

  • chcon -t var_lib_t $(dirname $(find /var/lib/mysql -maxdepth 0 -printf "%l)) (if /var/lib/mysql is a symlink)

If epages-webconf is installed, following parameters are set:

  • chcon -t httpd_config_t "$EPAGES_CONFIG"/WebInterface.conf

  • chcon -t httpd_modules_t "$EPAGES"/WebAdapter/{lib64/,}*.so

  • chcon -t httpd_log_t "$EPAGES_LOG"/WebAdapter.log 2>/dev/null

  • chcon -RL -t httpd_sys_content_t "$EPAGES_WEBROOT"

Then the web server cannot access to any other file than those menotioned above.

chcon -RL … is executed only if the directory in the argument not yet has the required context.

se-file-context.sh --set --perl-cgi

se-file-context.sh has an additional option --perl-cgi that allows the web server user to access ePages Perl, i.e. to use following files:

  • chcon -t bin_t "$EPAGES_SHARED"/Monitor/spy.pl "$EPAGES"/WebAdapter/monitor.pl

  • chcon -t httpd_sys_content_t "$EPAGES_SHARED"/Monitor/*.tmpl

  • chcon -RL -t usr_t "$EPAGES_CARTRIDGES"

  • chcon -RL -t bin_t "$EPAGES_PERL"/bin

  • find "$EPAGES_PERL"/bin -name ".so" -exec chcon -t lib_t {} \;

  • chcon -RL -t usr_t "$EPAGES_PERL"/lib

  • find "$EPAGES_PERL"/lib* -name ".so" -exec chcon -t lib_t {} \;

  • chcon -t texrel_shlib_t "$EPAGES_PERL"/lib/site_perl/linux/auto/Math/Pari/Pari.so

  • chcon -t texrel_shlib_t "$EPAGES_PERL"/bin/libMagickCore.so.2

  • chcon -t httpd_log_t "$EPAGES_LOG"/error.log "$EPAGES_LOG"/debug.log

Switching --perl-cgi on may be considered as security flaw. Don’t use --perl-cgi if there is no need to access Perl by the web server. Anyway, the access if only required if the CGI scripts spy.pl and monitor.pl (or other CGI scripts created by yourself) are used.

If both environment variables EPAGES_ENABLE_SELINUX and EPAGES_ENABLE_PERL_CGI are set in /etc/default/epages6, se-file-context.sh --set --perl-cgi is executed whenever starting an ePages application.

Default values in /etc/default/epages6 are EPAGES_ENABLE_SELINUX=1 and EPAGES_ENABLE_PERL_CGI=1. If you don’tz want to allow the web server user to run ePages Perl, unset EPAGES_ENABLE_PERL_CGI in /etc/default/epages6.

se-file-context.sh --restore

se-file-context.sh --restore restores the file context to its original value.

se-webnfs-context.sh

If the web server wants to access NFS mounted files (always in distributed installations) then

a) either run setsebool httpd_use_nfs on,

b) or mount all files needed by the web server with SELinux contect.

Variant a) has the drwaback that for the web server no files on the NFS mount is SELinux secured anymore.

se-webnfs-context.sh allows you to choose between both variants:

  • se-webnfs-context.sh --set mounts according variant b)

  • se-webnfs-context.sh --restore mounts according variant a)

Note: this only will work for ePages standard mounts as created by /var/epages/epages-fs.sh.

Variant a) works something like that:

mount FILESERVER:/srv/epages/eproot/Shared/WebRoot /srv/epages/eproot/Shared/WebRoot
setseboot httpd_use_nfs on
/etc/init.d/epages6 start_httpd

Variant b) works something like that:

SELINUX_OPTIONS='nosharecache,context=system_u:object_r:httpd_sys_content_t:s0'
mount -o $SELINUX_OPTIONS FILESERVER:/srv/epages/eproot/Shared/WebRoot /srv/epages/eproot/Shared/WebRoot
setseboot httpd_use_nfs off
/etc/init.d/epages6 start_httpd

Usage:

# se-webnfs-context.sh -?
Usage:
  ./se-webnfs-context.sh { --set | --restore } [ --perl-cgi ] [ --no-start ] [ --verbose ]
Options:
  --set     : mount web server files with SELinux context
  --restore : mount web server files with httpd_use_nfs on
  --perl-cgi: set additionally SELinux context for Perl files
  --no-start: do not start ePages at the end of the script
  --verbose : verbose output

SELinux Context for Distributed Installations

May server FILESERVER be the file server, request router and application server.

May server WEBSERVER be the web server and MySQL server.

Then run following commands (in that order) on the respecive servers to add the SELinux context to ePages (use your own UUID):

FILESERVER:

UUID=1234abcd-1234-1234-1234-0123456789abcd
export EPAGES_REPOURL=ftp://epages-software.de/repo/usr/$UUID
rpm -hiv $EPAGES_REPOURL/yum/epages-release.noarch.rpm
/var/epages/epages-fs.sh -share

WEBSERVER:

UUID=1234abcd-1234-1234-1234-0123456789abcd
export EPAGES_REPOURL=ftp://epages-software.de/repo/usr/$UUID
rpm -hiv $EPAGES_REPOURL/yum/epages-release.noarch.rpm
/var/epages/epages-fs.sh -mount FILESERVER

FILESERVER:

yum -y groupinstall epages-appsrv epages-reqsrv epages-ascsrv

WEBSERVER:

yum -y groupinstall epages-webconf epages-mysqld

FILESERVER:

. /etc/default/epages6
/var/epages/se-file-context.sh --set --perl-cgi --verbose

WEBSERVER:

. /etc/default/epages6
/var/epages/se-file-context.sh --set --perl-cgi --verbose
/var/epages/se-webnfs-context.sh --set --perl-cgi --no-start --verbose
/etc/init.d/epages6 start

FILESERVER:

/etc/init.d/epages6 start

Ready!

SELinux Context for Apache

What rights has the httpd process in in SELinux context?:

# semanage boolean -l | sort | grep httpd
allow_httpd_anon_write         -> off   Allow Apache to modify public files used for public file transfer services. Directories/Files must be labeled public_rw_content_t.
allow_httpd_mod_auth_ntlm_winbind -> off   Allow Apache to use mod_auth_pam
allow_httpd_mod_auth_pam       -> off   Allow Apache to use mod_auth_pam
allow_httpd_sys_script_anon_write -> off   Allow apache scripts to write to public content.  Directories/Files must be labeled public_rw_content_t.
httpd_builtin_scripting        -> on    Allow httpd to use built in scripting (usually php)
httpd_can_check_spam           -> off   Allow http daemon to check spam
httpd_can_network_connect_cobbler -> off   Allow HTTPD scripts and modules to connect to cobbler over the network.
httpd_can_network_connect_db   -> off   Allow HTTPD scripts and modules to connect to databases over the network.
httpd_can_network_connect      -> off   Allow HTTPD scripts and modules to connect to the network using TCP.
httpd_can_network_relay        -> off   Allow httpd to act as a relay
httpd_can_sendmail             -> off   Allow http daemon to send mail
httpd_dbus_avahi               -> on    Allow Apache to communicate with avahi service via dbus
httpd_enable_cgi               -> on    Allow httpd cgi support
httpd_enable_ftp_server        -> off   Allow httpd to act as a FTP server by listening on the ftp port.
httpd_enable_homedirs          -> off   Allow httpd to read home directories
httpd_execmem                  -> off   Allow httpd scripts and modules execmem/execstack
httpd_read_user_content        -> off   Allow httpd to read user content
httpd_setrlimit                -> off   Allow httpd daemon to change system limits
httpd_ssi_exec                 -> off   Allow HTTPD to run SSI executables in the same domain as system CGI scripts.
httpd_tmp_exec                 -> off   Allow Apache to execute tmp content.
httpd_tty_comm                 -> on    Unify HTTPD to communicate with the terminal. Needed for entering the passphrase for certificates at the terminal.
httpd_unified                  -> on    Unify HTTPD handling of all content files.
httpd_use_cifs                 -> off   Allow httpd to access cifs file systems
httpd_use_gpg                  -> off   Allow httpd to run gpg in gpg-web domain
httpd_use_nfs                  -> off   Allow httpd to access nfs file systems

setseboot VAR=1 switches on the desired variables:

setsebool httpd_builtin_scripting on
setsebool httpd_can_network_connect on
setsebool httpd_can_network_relay on
setsebool httpd_enable_cgi on
setsebool httpd_use_nfs on

Allow httpd to use a different port (e.g. port 81):

# semanage port -l | grep http
http_cache_port_t              tcp      3128, 8080, 8118, 10001-10010
http_cache_port_t              udp      3130
http_port_t                    tcp      80, 443, 488, 8008, 8009, 8443
pegasus_http_port_t            tcp      5988
pegasus_https_port_t           tcp      5989
# semanage port --add --proto tcp --type http_port_t 81
# semanage port -l | grep '^http_port_t$'
http_port_t                    tcp      81, 80, 443, 488, 8008, 8009, 8443

Show standard policies for httpd files:

# semanage fcontext -l | egrep -i '(Apache|httpd)'

Relabel Files

se-file-context.sh changes the context of files/directories. If the files are releabled, the changes get lost.

Thatswhy is is probably better to make the changes permanent:

# semanage fcontext --add --type httpd_sys_content_t '/srv/epages/eproot/Shared/WebRoot(/.*)?'
# restorecon -R /srv/epages/eproot/Shared/WebRoot
# semanage fcontext -l | grep eproot
/srv/epages/eproot/Shared/WebRoot(/.*)?   all files   system_u:object_r:httpd_sys_content_t:s0

/etc/selinux/targeted/contexts/customizable_types contains a list of file types. Ifa a file has such a type, it isn’t changed when relabelling:

# cat /etc/selinux/targeted/contexts/customizable_types
sandbox_file_t
svirt_image_t
virt_content_t
httpd_user_htaccess_t
httpd_user_script_exec_t
httpd_user_content_ra_t
httpd_user_content_rw_t
httpd_user_content_t
git_session_content_t
home_bin_t

Relabel all files of the server either by executing:

fixfiles relabel

or by executing:

touch /.autorelabel
reboot

Troubleshooting

If the web server can’t be restarted after running se-file-context.sh --restore:

# se-file-context.sh --restore --verbose
-> chcon --version: chcon (GNU coreutils) 8.4
-> getenforce: Enforcing
-> test -w /etc/passwd
=> epages-mysqld
=> epages-webconf
restorecon $EPAGES_CONFIG/WebInterface.conf
restorecon $EPAGES/WebAdapter/lib64/*.so $EPAGES/WebAdapter/*.so
restorecon $EPAGES_LOG/WebAdapter.log
restorecon -R $EPAGES_WEBROOT $EPAGES_WEBROOT/*
# cat /dev/null  > /var/log/audit/audit.log
# /etc/init.d/httpd start
Starting httpd: httpd: Syntax error on line 221 of /etc/httpd/conf/httpd.conf: Syntax error on line 76 of /etc/httpd/conf.d/zzz-epages-httpd.conf: Cannot load /srv/epages/eproot/WebAdapter/lib64/libWIApacheSSL-2.2.8.so into server: /srv/epages/eproot/WebAdapter/lib64/libWIApacheSSL-2.2.8.so: cannot open shared object file: Permission denied
[FAILED]

Then we want to know what went wrong:

# audit2why -i /var/log/audit/audit.log
type=AVC msg=audit(1290176592.874:101): avc:  denied  { read } for  pid=9172 comm="httpd" name="libWIApacheSSL-2.2.8.so" dev=dm-0 ino=278209 scontext=unconfined_u:system_r:httpd_t:s0 tcontext=system_u:object_r:var_t:s0 tclass=file
  Was caused by:
      Missing type enforcement (TE) allow rule.

Correct the contect and try again:

# chcon -t httpd_modules_t $EPAGES/WebAdapter/lib64/*.so
# cat /dev/null  > /var/log/audit/audit.log
# /etc/init.d/httpd start
Starting httpd:                                            [  OK  ]

Anyway, it still does not work:

# wget -nv -S http://localhost/WebRoot/Doc/Manual/de/User_concept.txt >/dev/null
http://localhost/WebRoot/Doc/Manual/de/User_concept.txt:
15:40:26 ERROR 403: Forbidden.

What went wrong?:

# tail -1 /var/log/httpd/error_log
[Fri Nov 19 15:40:26 2010] [error] [client 172.20.20.84] (13)Permission denied: access to /WebRoot/Doc/Manual/de/User_concept.txt denied
# audit2why -i /var/log/audit/audit.log
type=AVC msg=audit(1290177626.043:118): avc:  denied  { getattr } for  pid=9313 comm="httpd" path="/srv/epages/eproot/Shared/WebRoot/Doc/Manual/de/User_concept.txt" dev=dm-0 ino=288079 scontext=unconfined_u:system_r:httpd_t:s0 tcontext=system_u:object_r:var_t:s0 tclass=file
  Was caused by:
     Missing type enforcement (TE) allow rule.

Solution:

# se-file-context.sh --set --verbose
-> chcon --version: chcon (GNU coreutils) 8.4
-> getenforce: Enforcing
-> test -w /etc/passwd
=> epages-mysqld
=> epages-webconf
chcon -t httpd_config_t $EPAGES_CONFIG/WebInterface.conf
chcon -t httpd_modules_t $EPAGES/WebAdapter/lib64/*.so $EPAGES/WebAdapter/*.so
chcon -t httpd_log_t $EPAGES_LOG/WebAdapter.log
chcon -RL -t httpd_sys_content_t $EPAGES_WEBROOT

SELinux Context for MySQL

What rights has the MySQL process in in SELinux context?:

# semanage boolean -l | sort | grep mysql
allow_user_mysql_connect       -> off   Allow users to connect to mysql
exim_can_connect_db            -> off   Allow exim to connect to databases (postgres, mysql)
ftpd_connect_db                -> off   Allow ftp servers to use connect to mysql database
mysql_connect_any              -> off   Allow mysqld to connect to all ports

setseboot VAR=1 switches on the desired variables:

setsebool allow_user_mysql_connect on

Allow specific MySQL ports:

# semanage port -l | grep mysql
mysqld_port_t                  tcp      1186, 3306, 63132-63164
mysqlmanagerd_port_t           tcp      2273

Show standard policies for mysql files:

# semanage fcontext -l | grep mysql

Move /var/lib/mysql to Different Directory

First move /var/lib/mysql ans create a symbolic link:

/etc/init.d/mysqld stop
mv /var/lib/mysql /some/local/directory/
( cd /var/lib ; ln -s /some/local/directory/mysql )

Finally execute se-file-context.sh --set. This sets the SELinux context of following files:

chcon -h system_u:object_r:mysqld_db_t:s0 /var/lib/mysql
chcon -h system_u:object_r:var_lib_t:s0 /some/local/directory

Move /var/lib/mysql to File Server

mysql.sock

Even if /var/lib/mysql resides on a different server, mysql.sock must remain local. Also, the directory that contains mysql.sock, must have a special SELinux context (/tmp/mysql/ may vary):

/etc/init.d/mysqld stop
sed -i 's,^\(socket\)=.*,\1=/tmp/mysql/mysql.sock,' /etc/my.cnf
mkdir -m 755 -p /tmp/mysql
chown mysql:mysql /tmp/mysql
semanage fcontext --add --type mysqld_db_t '/tmp/mysql(/.*)?'
semanage fcontext -f -s --add --type mysqld_var_run_t '/tmp/mysql/mysql\.sock'
restorecon -R /tmp/mysql

Note that $EPAGES_CONFIG/Database.d/*.conf must have the right datasource=dbi:mysql, either the new socket or a TCP connection:

# either:
datasource=dbi:mysql:mysql_socket=/tmp/mysql/mysql.sock;...
# or:
datasource=dbi:mysql:hostname=mysql-server;port=3306;...

Example:

cd $EPAGES_CONFIG
for i in Database.d/*.conf ; do
  sed -i 's,^\(datasource=dbi:mysql\),\1:hostname='`hostname`';port=3306,' $i
done

mount FILESERVER:lib/mysql

Assumed that lib/mysql is stored in /home/lib/mysql on the file server $FILESERVER. The file server shares /home/lib/mysql (or a superior directory). Then /home/lib/mysql is mounted as follows:

mkdir -m 755 -p /var/lib/mysql
MOUNT_OPT='async,exec,noatime,nodev,nolock,bg,hard,intr,rw,rsize=16384,wsize=16384'
SELINUX_MOUNT_OPT='nosharecache,context=system_u:object_r:mysqld_db_t:s0'
echo "$FILESERVER:/home/lib/mysql /var/lib/mysql nfs $SELINUX_MOUNT_OPT,$MOUNT_OPT 0 0" >> /etc/fstab
mount /var/lib/mysql

The SELinux mount options are necessary because otherwise the mounted files would get the context nfs_t and therefore couldn’t be read by mysqld.

The SELinux mount option nosharecache is only necessary if the share is mounted twice.