Trouble with custom SELinux modules

Hello Everyone!

I’m here with second part of series on how to create a custom SELinux policy rpm package. In this part I’ll show disadvantages of this concept and explain a possible solution for future.

 

The concept of using a custom SELinux policy for your service works fine, but it’s limited by the m4 macro language used to write SELinux policies. The limitation lies in the fact that you can’t use a macro definition from your custom policy in the distribution policy. A nice example of this problem is the following bug.

 

When you try to build the selinux-policy rpm package you’ll end up with:

 

/usr/bin/checkmodule -M -m tmp/abrt.tmp -o tmp/abrt.mod
policy/modules/contrib/abrt.te:256:ERROR 'syntax error' at token 'docker_stream_connect' on line 12012:
	docker_stream_connect(abrt_t)
#line 256
/usr/bin/checkmodule:  error(s) encountered while parsing configuration
/usr/bin/checkmodule:  loading policy configuration from tmp/abrt.tmp
Rules.modular:74: recipe for target 'tmp/abrt.mod' failed
make: *** [tmp/abrt.mod] Error 1
error: Bad exit status from /var/tmp/rpm-tmp.B2uAfi (%install)

ABRT daemon adds support for collecting information about containers. For examples it runs:

#docker inspect $container_id
to detect a new crash in a docker container. From the SELinux point of view,  the policy for ABRT daemon needs to be changed. This is expected behaviour. The solution here is pretty simple, we just need to add this rule:

 

docker_stream_connect(abrtd_t)
This allows ABRT daemon to connect with docker over a unix stream socket. The rule needs to be included in the abrt SELinux module of distribution policy. However, the definition of

 

docker_stream_connect()
is in the docker-selinux rpm package. That is very similar to the situation when you are compiling some code written in C and you forgot to include a required header file. In this situation, the rpm package of selinux-policy cannot be build due to a missing definition.
We found a solution! Before every distribution policy package build, we download the docker policy files from github. We archive these files and distribute them along with the distribution policy source files. During build, these files are extracted and the docker interface file (*.if) is merged with all the other interface files. Using this method, we could add the rule mentioned above in the distribution policy.

 

Now, I’ll show you how to make all changes to fix this issue:

We need to install these rpm packages:

# dnf install fedpkg

We create an archive with all SELinux custom module source files:

# tar -czf /tmp/myapp-selinux.tgz myapp.if myapp.te myapp.fc
Then we clone the selinux-policy rpm sources and move it to the current working directory:

 

# fedpkg clone selinux-policy
# cd selinux-policy
# mv /tmp/myapp-selinux.tgz ./
In selinux-policy.spec file we need to add the new source file and extract this archive in the %prep phase of a build:

 

 Source36: myapp-selinux.tgz
 tar -xf %{SOURCE36}

Diff looks like this:

$ git diff
diff --git a/selinux-policy.spec b/selinux-policy.spec
index f052550..9b932cf 100644
--- a/selinux-policy.spec
+++ b/selinux-policy.spec
@@ -19,7 +19,7 @@
 Summary: SELinux policy configuration
 Name: selinux-policy
 Version: 3.13.1
-Release: 161%{?dist}
+Release: 162%{?dist}
 License: GPLv2+
 Group: System Environment/Base
 Source: serefpolicy-%{version}.tgz
@@ -57,6 +57,7 @@ Source30: booleans.subs_dist
 Source33: manpages_html.tgz
 Source34: manpages_man.tgz
 Source35: docker-selinux.tgz
+Source36: myapp-selinux.tgz
 Url: http://github.com/TresysTechnology/refpolicy/wiki
 BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
 BuildArch: noarch
@@ -310,6 +311,7 @@ done
 %setup -n serefpolicy-contrib-%{version} -q -b 29
 %patch1 -p1
 tar -xf %{SOURCE35}
+tar -xf %{SOURCE36}
 contrib_path=`pwd`
 %setup -n serefpolicy-%{version} -q
 %patch -p1

You increment release of build and run:

 # fedpkg mockbuild
It will build a new SELinux package including the interface file from our custom module called myapp. From now on, you can add interfaces from your custom module to the distribution policy, like in abrtd example above.
This  series of blogs showed how to easily create a custom SELinux module, ship it as rpm package or subpackage and dealt with issues of current SELinux technologies.