Apache Tomcat mod_jk with selinux
I am using Selinux with targeted policy on Centos 5.2. Centos is repackaging the Redhat Enterprise sources. As a consequence, the following procedure should more or less apply to Fedora and Redhat as well. Please note, that I am a beginner finding my way through Selinux.
The problem
While configuring my system, I set Selinux to permissive to log denied messages but still to allow the application to proceed.
I got the following error message in /var/log/audit/audit.log
type=AVC msg=audit(1221345997.761:142513): avc: denied { unlink } for pid=13703 comm="httpd" name="jk-runtime-status.13703.lock" dev=dm-1 ino=2284901 scontext=user_u:system_r:httpd_t:s0 tcontext=user_u:object_r:httpd_log_t:s0 tclass=file type=SYSCALL msg=audit(1221345997.761:142513): arch=c000003e syscall=87 success=yes exit=0 a0=2b27f82a6190 a1=7080 a2=0 a3=12 items=0 ppid=1 pid=13703 auid=500 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=(none) ses=698 comm="httpd" exe="/usr/sbin/httpd" subj=user_u:system_r:httpd_t:s0 key=(null)
The first message means that something running under the context user_u:system_r:httpd_t:s0 tries to access a file (tclass=file) which has the Selinux context user_u:object_r:httpd_log_t:s0
. The filename is
jk-runtime-status.13703.lock. Selinux denied unlink on the file. What does this mean?
The only source to explain the permission was the website http://seedit.sourceforge.net/doc/access_vectors/
So unlink means deleting a file. The mod_jk module in Apache uses the jk-runtime-status file and tries to delete it.
Solving the problem
I used the following means to analyse the problem
grep http /var/log/audit/audit.log | audit2why
More precise is the search tool in Selinux
ausearch --comm httpd | audit2why
Note that ausearch will search all audit.log files including the older ones as well. Have a look on its manpage it is well documented.
The only problem is that audit2why tells me nothing useful.
A different approach are the troubleshooting tools. They can run as visual application or just on the console. Well, I have a server so there is no visual environment.
If you can’t run sealert than just install it:
yum install setroubleshoot-server
First extract all httpd messages and write them to httpd.log
ausearch —comm httpd > httpd.log
To get the messages of today just use
ausearch —comm httpd —start today > httpd.log
Now run
sealert -a httpd.log
I got the following message:
Summary:SELinux prevented httpd reading and writing access to http files.
Detailed Description:
[SELinux is in permissive mode, the operation would have been denied but was
permitted due to permissive mode.]SELinux prevented httpd reading and writing access to http files. Ordinarily
httpd is allowed full access to all files labeled with http file context. This
machine has a tightened security policy with the httpd_unified turned off, this
requires explicit labeling of all files. If a file is a cgi script it needs to
be labeled with httpd_TYPE_script_exec_t in order to be executed. If it is
read-only content, it needs to be labeled httpd_TYPE_content_t, it is writable
content. it needs to be labeled httpd_TYPE_script_rw_t or
httpd_TYPE_script_ra_t. You can use the chcon command to change these contexts.
Please refer to the man page “man httpd_selinux” or FAQ
(http://fedora.redhat.com/docs/selinux-apache-fc3) “TYPE” refers to one of
“sys”, “user” or “staff” or potentially other script types.
Allowing Access:
Changing the “httpd_unified” boolean to true will allow this access: “setsebool
-P httpd_unified=1”
The following command will allow this access:
setsebool -P httpd_unified=1
……….. snip ……….
I am confused. The trouble shooting tools thinks that this is a html file but at least it explains correctly, that httpd tries to write to this file.
If proposes two solution:
a)
Change the context of the file to
httpd_TYPE_script_rw_t
This allow writing of httpd to this file but hey, this would allow any php to write to this file as well. This is not what I want.
b)
setsebool -P httpd_unified=1
From my understanding this allows to write everything which is readable from httpd. This is not what I want as well.
Well this is a lock file and might change the context of the file to something that httpd_t can write and unlink.
Let’s have a look in the normal pid file directory
ls -Z /var/run
I found probably something useful
rw-r-r— root root system_u:object_r:httpd_var_run_t httpd.pid
Pid files have the context httpd_var_run
Let us check which access httpd has. sesearch is a great help to do this.
sesearch —allow -s httpd_t | grep httpd_var_run
The result is
allow httpd_t httpd_var_run_t : file { ioctl read write create getattr setattr lock append unlink link rename };
allow httpd_t httpd_var_run_t : dir { ioctl read write getattr lock add_name remove_name search };
allow httpd_t httpd_var_run_t : sock_file { ioctl read write create getattr setattr lock append unlink link rename };
The first line tells us httpd_t can do everything in {..} to a file having the context httpd_var_run_t.
Let us try to create the jk_runtime file in a folder so that it gets the httpd_var_run_t context by default.
mkdir /var/run/mod_jk semanage fcontext -a -t httpd_var_run_t "/var/run/mod_jk(/.*)?"
I changed the mod_jk configuration, which can be somewhere in your httpd.conf or close to it.
JkShmFile /var/run/mod_jk/jk-runtime-status
After a restart of httpd, I can see the lock files in /var/run/mod_jk and ta-ta-ta let’s see the file context of Selinux.
lsZ /var/run/mod_jk-r— root root user_u:object_r:httpd_var_run_t jk-runtime-status.6940
-rw-r
rw-r-r— root root user_u:object_r:httpd_var_run_t jk-runtime-status.6940.lock
Perfect. Let us check the audit.log a last time, if anything unwanted rests in the log file.
tail /var/log/audit/audit.log
No, not this time. So we are done.
Best Regards
Sebastian Hennebrueder