I am working on a new project that must be secured with SELinux. We have a custom binary written in C (for the sake of this question it will be called "testprog") that needs to switch to it's own context so that we can confine it's operations, rather than letting it run in the unconfined domain.
I have created a simple sample policy file based on the learning I have done so far, but bash failed to execute the binary.
Here is the policy file as it exists so far:
policy_module(testprog, 0.1.6)
require {
type unconfined_t;
class file { ioctl getattr setattr create read write unlink open relabelto };
class process transition;
type fs_t;
class filesystem getattr;
}
type testprog_t;
type testprog_exec_t;
allow testprog_t fs_t:filesystem getattr;
allow testprog_t testprog_exec_t : file { ioctl read getattr lock execute execute_no_trans entrypoint open } ;
type_transition unconfined_t testprog_exec_t : process testprog_t;
allow unconfined_t testprog_t : process transition ;
I have set the context of the binary itself as follows:
-rwxr-xr-x. root root system_u:object_r:testprog_exec_t:s0 /usr/bin/testprog
However if I try and execute the command from the bash shell, I get a permission denied
error and denial's logged in audit.log:
[root@selinux-dev ~]# testprog
type=AVC msg=audit(1504546613.537:237): avc: denied { getattr } for pid=1300 comm="bash" path="/usr/bin/testprog" dev="dm-0" ino=34637336 scontext=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 tcontext=system_u:object_r:testprog_exec_t:s0 tclass=file
type=SYSCALL msg=audit(1504546613.537:237): arch=c000003e syscall=4 success=no exit=-13 a0=2518ca0 a1=7ffd90223980 a2=7ffd90223980 a3=0 items=0 ppid=1296 pid=1300 auid=1000 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts0 ses=2 comm="bash" exe="/usr/bin/bash" subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 key=(null)
type=PROCTITLE msg=audit(1504546613.537:237): proctitle="-bash"
type=AVC msg=audit(1504546613.537:238): avc: denied { getattr } for pid=1300 comm="bash" path="/usr/bin/testprog" dev="dm-0" ino=34637336 scontext=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 tcontext=system_u:object_r:testprog_exec_t:s0 tclass=file
type=SYSCALL msg=audit(1504546613.537:238): arch=c000003e syscall=4 success=no exit=-13 a0=2518ca0 a1=7ffd90223980 a2=7ffd90223980 a3=0 items=0 ppid=1296 pid=1300 auid=1000 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts0 ses=2 comm="bash" exe="/usr/bin/bash" subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 key=(null)
type=PROCTITLE msg=audit(1504546613.537:238): proctitle="-bash"
-bash: testprog: command not found
Clearly my policy is a little over the top. Ultimately I want to be able to run the binary from systemd (my unit file, very simple, is shown below), but I want to transition the process from a bash shell and from systemd into the testprog_t type I have created.
[Unit]
Description=SELinux Test Program
[Service]
#Type=forking
# The PID file is optional, but recommended in the manpage
# "so that systemd can identify the main process of the daemon"
PIDFile=/var/run/testprog.pid
ExecStart=/usr/bin/testprog /etc/testprog.conf /var/run/testprog.pid
[Install]
WantedBy=multi-user.target
Please can anyone help me see where I have gone wrong? Underlying operating system is RHEL 7.4
Thanks!
Best Answer
I got the transition working in the end thanks to a number of references - it actually turned out to be incredibly simple and I guess you could say related to a basic rule of good programming?
In the policy I posted in the question, I had defined two new types:
And then proceeded to allow various things to happen with these types, and also specified a type transition:
However at no point had I actually told SELinux what these types actually were. For example I set the context of the
/usr/bin/testprog
file tosystem_u:object_r:testprog_exec_t:s0
but I never actually told SELinux through my policy that testprog_exec_t was a file. As soon as I changed the policy by adding type specifications, things began to look more promising. I also needed to use the role statement to allowtestprog_t
to run under theunconfined_r
role that shell commands typically run under on a RHEL system in targeted SELinux mode. The current fragment of the policy relating to this look like this:With this done, the type transition happens perfectly and the job of completing the policy has become one of using
sealert
to explore the behaviour of the program and to put the right policies in place to allow it to work as desired.I am hoping to put together a full worked example of a non-SELinux aware application that needs to run in it's own confined context rather than unconfined for my colleagues (and anyone else who needs it) - it's all rather skeletal right now but if anyone is interested in tracking it you can find the code here:
https://github.com/jamesfreeman959/selinux-testprog