To test the effects of the new module, let us create a sample
index.html
file in the DocumentRoot folder of Apache:[root@vbg ~]# echo "The Art of Guard - Part VII " > /var/www/html/index.html [root@vbg ~]# service httpd start
To check if all is fine, let us view the Web page using elinks:
[root@vbg ~]# elinks --dump http://localhost The Art of Guard - Part VII
This shows that all is indeed fine and Apache can serve our document on the website. Let us now change the type of
index.html
to lfy_t
and see what happens:[root@vbg ~]# chcon -t lfy_t /var/www/html/index.html chcon: failed to change context of `/var/www/html/index.html' to `system_u:object_r:lfy_t:s0': Permission denied
We have received an error message! The SELinux policy on my system does not allow us to change the type of the file
/var/www/html/index.html
to lfy_t
.
But what is the current type of
/var/www/html/index.html
? To check the security context ofindex.html
, use the following command:[root@vbg ~]# ls -lZ /var/www/html/index.html -rw-r--r--. root root system_u:object_r:httpd_sys_content_t:s0 /var/www/html/index.html
We can see that the default type allotted to this file (SELinux object) is
httpd_sys_content_t
. Why is it so? We did not specify the file type when creating it. Why did it take this particular type and not tmp_t
or some other type?
By default, newly created objects and subjects take the type of their parent object and subject, respectively. Since the folder
/var/www/html/
is of the type httpd_sys_content_t
, any new files created under it will also get the same type, unless you want it otherwise. The same applies to processes (or ‘subject’ in SELinux terminology).
Since SELinux is not allowing us to change the security context of our file to
lfy_t
, we will need to write a few allow rules and include them in our policy. As discussed in the earlier article, the best way is to add these allow rules to our Policy Module.
But first we need to understand why exactly this action is being disallowed. Let us turn to the log files for help:
[root@vbg ~]# tailf /var/log/audit/audit.log type=AVC msg=audit(1261193853.109:39): avc: denied { relabelto } for pid=2293 comm="chcon" name="index.html" dev=sda2 ino=104970 scontext=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 tcontext=system_u:object_r:lfy_t:s0 tclass=file type=SYSCALL msg=audit(1261193853.109:39): arch=c000003e syscall=188 success=no exit=-13 a0=1a660e0 a1=3dece15649 a2=1a67660 a3=1b items=0 ppid=1960 pid=2293 auid=500 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts0 ses=1 comm="chcon" exe="/usr/bin/chcon" subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 key=(null) type=USER_AUTH msg=audit(1261194789.950:40): user pid=2313 uid=500 auid=500 ses=1 subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 msg='op=PAM:unix_chkpwd acct="vbg" exe="/sbin/unix_chkpwd" hostname=? addr=? terminal=? res=success'
Now we can see from the AVC Denial message in the Audit Log that
relabelto
permission is denied to the source context unconfined_t
(bash process—my shell) for the target context lfy_t
. Going by our earlier discussion (in Part 5), we could create an allow rule for the above in our test.te
file:allow unconfined_t lfy_t : file { relabelto }
But will this solve the above-mentioned issue? Will not other SELinux denials crop up?
The important thing to remember is that SELinux permissive mode has been given for exactly this reason—troubleshooting. So let us take the system into permissive mode and see if any more errors occur:
[root@vbg ~]# getenforce Enforcing [root@vbg ~]# setenforce 0 [root@vbg ~]# getenforce Permissive
Let us also clear the log file so that it contains only the latest errors. But we cannot afford to lose important logs. So we need to first make a copy of the current log file:
[root@vbg ~]# cat /var/log/audit/audit.log > /var/log/audit/my-audit-log-19Dec09
Now, let us empty the log file:
[root@vbg ~]# >/var/log/audit/audit.log
…and repeat the
chcon
command:[root@vbg ~]# chcon -t lfy_t /var/www/html/index.html
Let us have a look at AVC denial messages in the new log file:
[root@vbg ~]# cat /var/log/audit/audit.log | grep -i deni type=AVC msg=audit(1261195413.081:42): avc: denied { relabelto } for pid=2328 comm="chcon" name="index.html" dev=sda2 ino=104970 scontext=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 tcontext=system_u:object_r:lfy_t:s0 tclass=file type=AVC msg=audit(1261195413.081:42): avc: denied { associate } for pid=2328 comm="chcon" name="index.html" dev=sda2 ino=104970 scontext=system_u:object_r:lfy_t:s0 tcontext=system_u:object_r:fs_t:s0 tclass=filesystem
We can see that two actions are disallowed. Let us write the allow rules for them:
allow unconfined_t lfy_t : file { relabelto } allow lfy_t fs_t : filesystem { associate }
Let us update our module policy file,
test.te
:[vbg@vbg test-selinux]$ vim test.te policy_module(test, 1.1) type lfy_t; allow unconfined_t lfy_t : file { relabelto }; allow lfy_t fs_t : filesystem { associate };
Save and close. (Do note that we have now increased the version number to 1.1.)
Compile the
test.te
source file by running the make command:[vbg@vbg test-selinux]$ make test.pp Compiling targeted test module /usr/bin/checkmodule: loading policy configuration from tmp/test.tmp test.te":5:ERROR 'unknown type unconfined_t' at token ';' on line 3199: allow unconfined_t lfy_t : file { relabelto }; /usr/bin/checkmodule: error(s) encountered while parsing configuration make: *** [tmp/test.mod] Error 1
Oops! We have received an error while compiling our module!
This is because we have not defined the types and classes used elsewhere in our source file (
test.te
). But are these types not already defined in the policy? Doesn’t unconfined_t
exist already?
It does, but we need to explicitly define which types and classes are required for our module. To solve this error, let us define the types in the required section of our source file. We explicitly add the following lines to our source:
require { type unconfined_t; type fs_t; }
So that the new
test.te
is:[vbg@vbg test-selinux]$ cat test.te policy_module(test, 1.1) require { type unconfined_t; type fs_t; } type lfy_t; allow unconfined_t lfy_t : file { relabelto }; allow lfy_t fs_t : filesystem { associate };
Let us now compile this again:
[vbg@vbg test-selinux]$ make test.pp Compiling targeted test module /usr/bin/checkmodule: loading policy configuration from tmp/test.tmp /usr/bin/checkmodule: policy configuration loaded /usr/bin/checkmodule: writing binary representation (version 10) to tmp/test.mod Creating targeted test.pp policy package rm tmp/test.mod.fc tmp/test.mod
This has successfully created our upgraded policy package. Thus the important points to remember while creating the code for a policy module are:
- Specify all existing types of the policy in a required section in the source file.
- Specify all new types to be created outside the required section.
Let us now upgrade the version in the policy and check:[root@vbg test-selinux]# semodule -u test.pp [root@vbg test-selinux]# semodule -u test.pp [root@vbg test-selinux]# semodule -l | grep test test 1.1That shows that our latest version is now loaded.Let us now try to re-label/var/www/html/index.html
fromhttpd_sys_content_t
tolfy_t
:[root@vbg test-selinux]# setenforce 1 [root@vbg test-selinux]# chcon -t lfy_t /var/www/html/index.html chcon: cannot access `/var/www/html/index.html': Permission deniedAgain, there are some more errors! Is it that SELinux is too cumbersome to troubleshoot? Till when do we need to keep on looking at these errors and generate rules? This would be a very demotivating and time-consuming task. Fortunately, a splendid tool calledaudit2allow
comes to our rescue.audit2allow
generates SELinux policy allow rules from the logs of denied operations. It parses the log file and creates corresponding allow rules.Let us repeat the above steps to generate AVC Denial logs in the audit log file.[root@vbg test-selinux]# setenforce 0 [root@vbg test-selinux]# > /var/log/audit/audit.log [root@vbg test-selinux]# cat /var/log/audit/audit.log | audit2allow #============= unconfined_t ============== allow unconfined_t lfy_t:file getattr;audit2allow
has many helpful options. Do ensure that you go through the man page in detail. To generate the “required” section for already existing system types and classes, use the option-r
withaudit2allow
:[root@vbg test-selinux]# cat /var/log/audit/audit.log | audit2allow -r require { type unconfined_t; type lfy_t; class file getattr; } #============= unconfined_t ============== allow unconfined_t lfy_t:file getattr;We can redirect these required statements to our policy module source file:[root@vbg test-selinux]# cat /var/log/audit/audit.log | audit2allow -r >> /home/vbg/test-selinux/test.teAll we need to do now is edit the resultingtest.te
file, remove the declaration of typelfy_t
from the required section and keep a single required section. Finally, ourtest.te
should look like the one below:[vbg@vbg test-selinux]$ cat test.te policy_module(test, 1.1.1) require { type unconfined_t; type fs_t; class file getattr; } type lfy_t; allow unconfined_t lfy_t : file { relabelto }; allow lfy_t fs_t : filesystem { associate }; allow unconfined_t lfy_t:file getattr;All we need to do is to compile and load this policy module:[vbg@vbg test-selinux]$ make test.pp Compiling targeted test module /usr/bin/checkmodule: loading policy configuration from tmp/test.tmp /usr/bin/checkmodule: policy configuration loaded /usr/bin/checkmodule: writing binary representation (version 10) to tmp/test.mod Creating targeted test.pp policy package rm tmp/test.mod.fc tmp/test.mod [root@vbg test-selinux]# semodule -u test.pp [root@vbg test-selinux]# semodule -l | grep test test 1.1.1 [root@vbg test-selinux]# setenforce 1 [root@vbg test-selinux]# chcon -t lfy_t /var/www/html/index.html [root@vbg test-selinux]# ls -lZ /var/www/html/index.html -rw-r--r--. root root system_u:object_r:lfy_t:s0 /var/www/html/index.htmlFinally, with the help of the wonderfulaudit2allow
tool, we have been able to re-label the/var/www/html/index.html
file to the typelfy_t
. Can we now view the output of this file?[root@vbg ~]# elinks --dump http://localhost Forbidden You don't have permission to access / on this server. -------------------------------------------------------------------------- Apache/2.2.13 (Fedora) Server at localhost Port 80Changing the Security Context type fromhttpd_sys_content_t
tolfy_t
has caused this SELinux denial. Thesetroubleshoot
daemon popped up and recommended runningrestorecon
on/var/www/html/index.html
to restore its context to the original one.As a simple exercise, it is left to you to modify the policy module to permit thehttpd
service read access to the files of typelfy_t
. Please remember the rules covered above and also use theaudit2allow
command to generate the desired source.In the next article of this series, we will look at how to set default security contexts for files using policy modules. We will also use policy modules to set rules that will automatically assign the typelfy_t
to all files created in the Apache DocumentRoot folder.
0 comments
Post a Comment