Using rpm macros in product SELinux subpackages

Some time ago, I published a post about shipping custom SELinux modules together with product as rpm subpackage. One of the steps  in shipping custom SELinux module is creating a  spec file for SELinux package, which can be messy, especially %post and %postun phases.

In order to simplify writing spec files, we have created several macros.

Loading custom SELinux modules

First improvement concerns loading and removing custom SELinux modules. You can see the difference in the following example:

Without macros:

%post
#
# Install all modules in a single transaction
#
%_format MODULES %{_datadir}/selinux/packages/$x.pp.bz2
%{_sbindir}/semodule -n -s %{selinuxtype} -i $MODULES
if %{_sbindir}/selinuxenabled ; then
    %{_sbindir}/load_policy
    %relabel_files
fi
 
 
%postun
if [ $1 -eq 0 ]; then
	%{_sbindir}/semodule -n -r %{modulenames} &> /dev/null || :
	if %{_sbindir}/selinuxenabled ; then
		%{_sbindir}/load_policy
		%relabel_files
	fi
fi


With macros:

%post
#
# Install all modules in a single transaction
#
%_format MODULES %{_datadir}/selinux/packages/$x.pp.bz2
%selinux_modules_install -s %{selinuxtype} $MODULES
 
%postun
if [ $1 -eq 0 ]; then
    %selinux_modules_uninstall -s %{selinuxtype} $MODULES
fi

As you can see, module loading is done by one macro instead of 5 lines of code.

Labeling objects from custom policy

Next improvement in spec file is a pair of macros connected to labeling files coming from the custom policy. There is no need to specify all objects in spec file as we did in previously.

# Relabel files
%global relabel_files() \ # ADD files in *.fc file

Instead of specifying objects labeled by custom policy, following macros can be used:

%pre
%selinux_relabel_pre -s %{selinuxtype}

%posttrans
%selinux_relabel_post -s %{selinuxtype}

These macros will handle labeling objects coming from the custom SELinux module and after successfull package installation, all new objects should have correct SELinux label.

Handling SELinux booleans

Last improvement is setting booleans by macros. These macros provide solution for handling booleans in spec files and behave as follows:

  • If a boolean mentioned in the product .spec file was not set by user previously, it will be changed in the %post install phase and reverted during the %post uninstall phase will.
  • If a boolean mentioned in the product .spec file was set by user previously, it will be changed to a value from this file. However, it will not be reverted during the uninstallation of a product SELinux subpackage.

Usage of booleans macros:

# In preamble define booleans and values which should be used
%global selinuxbooleans booleanname=1 booleanname2=0

# Also some new packages will be needed:
%if 0%{?fedora}
Requires(post): policycoreutils-python-utils
%else
Requires(post): policycoreutils-python
%endif

# use selinux_set_booleans after custom SELinux module is loaded.

%post
%selinux_modules_install -s %{selinuxtype} $MODULES
%selinux_set_booleans -s %{selinuxtype} %{selinuxbooleans}

%postun
%selinux_modules_uninstall -s %{selinuxtype} $MODULES
%selinux_unset_booleans -s %{selinuxtype} %{selinuxbooleans}

All these improvements can be used in Fedora Rawhide and Fedora 26. Repository with sources can be found here.