Powered by Blogger.

Monday, March 17, 2014

The Art of Guard - Part VII

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:
  1. Specify all existing types of the policy in a required section in the source file.
  2. 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.1
That shows that our latest version is now loaded.
Let us now try to re-label /var/www/html/index.html from httpd_sys_content_t to lfy_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 denied
Again, 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 called audit2allow 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.te
All we need to do now is edit the resulting test.te file, remove the declaration of type lfy_t from the required section and keep a single required section. Finally, our test.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.html
Finally, with the help of the wonderful audit2allow tool, we have been able to re-label the/var/www/html/index.html file to the type lfy_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 80
Changing the Security Context type from httpd_sys_content_t to lfy_t has caused this SELinux denial. The setroubleshoot daemon popped up and recommended running restorecon 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 the httpd service read access to the files of type lfy_t. Please remember the rules covered above and also use the audit2allowcommand 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 type lfy_t to all files created in the Apache DocumentRoot folder.

0 comments

Post a Comment