Can we use SELinux for debugging of an application?
From time to time I am not able to find out a solution for a bug simply. I need to know if an access is really needed and which command or function causes it. This is the time for debugging.
I guess you know tools like strace, gdb, which help us with debugging. Today I would like to show you how SELinux could help us to understand what an application, a script or a command does.
I have recently got the following AVC msg:
type=AVC msg=audit(1328313263.274:55): avc: denied { read } for pid=869 comm=”smartdnotify” name=”group” dev=(removed) ino=293602 scontext=system_u:system_r:fsdaemon_t:s0 tcontext=system_u:object_r:passwd_file_t:s0 tclass=filenode=(removed)
which tells me that the fsdaemon_t domain is trying to access to the /etc/group file with the passwd_file_t label.
$ grep -r passwd_file_t /etc/selinux/targeted/contexts/files/
So I need to find a part of code which needs this access. Usually we see a similar AVC message if a getpw* function is called. That is the time for nm and grep commands.
$ nm -D PATHTO_BINARY |grep getpw
$ grep -r getpw SOURCE_CODE
If you get a result, you will be happy. If not, you need to continue with finding.
Our issue is a case where the smartdnotify command, which causes AVC message, is a shell script. I looked at this script and I got it.
$ cat /usr/libexec/smartmontools/smartdnotify |grep who
for t in $(who | awk ‘{ print $2; }’ | grep -e ‘^tty’ -e ‘^pts/’)
But what to do if you don’t know that the “who” command reads the /etc/group file? You could try to use SELinux to find out an answer. Everything what you need to do is to use SELinux tools.
1. Turn on full auditing system.
$ echo “-w /etc/shadow -p w” >> /etc/audit/audit.rules
$ service auditd restart
2. Generate a local test policy for the “who” command (or your application).
$ sepolgen -n debugwho -t 0 PATHTO/who
3. Remove the context declaration from the debugwho.fc policy file. It might cause a problem with a duplicate declaration.
$ echo “#no context” > debugwho.fc
$ sh debugwho.sh
$ chcon -t debugwho_exec_t PATHTO/who
Now you have loaded debug policy and you need to run the “who” command in this domain.
$ runcon -t system_u -r system_r -t initrc_t — runcon debugwho_t — who
The following transition will happen:
unconfined_t -> initrc_t -> debugwho_t
$ ausearch -m avc -ts recet |grep passwd
type=AVC msg=audit(1328540990.575:125): avc: denied { read } for pid=2258 comm=”who” name=”group” dev=”dm-1″ ino=527060 scontext=system_u:system_r:debugwho_t:s0-s0:c0.c1023 tcontext=system_u:object_r:passwd_file_t:s0 tclass=file
and you won.
Imagine you use it for more complicated applications, services which use python bindings for example.