No edit summary |
No edit summary |
||
(14 intermediate revisions by 4 users not shown) | |||
Line 1: | Line 1: | ||
{{admon/warning| | {{admon/warning | This document is outdated. Please use https://fedoraproject.org/wiki/SELinux/IndependentPolicy instead.}} | ||
= Creating Own Product Policies = | |||
{{admon/warning|Not official packaging guidelines|The contents of this document have not been reviewed by the [[Packaging Committee]] and do not constitute a set of packaging guidelines.}} | |||
In Fedora, there is a lot of applications and daemons which require customized SELinux security policy. The former approach with providing all policies only as a part of the system has been enhanced by the option to create custom product policy. | |||
With the possibility to create custom product policy, required changes in a policy can be released immediately, so the product package maintainer does not need to wait for another SELinux policy package release. In other words, a product SELinux policy is always synchronized with the corresponding product (package). | |||
This chapter is dedicated to shipping custom SELinux security module as a subpackage for a daemon or an application. | |||
{{admon/important|Responsibility|SELinux policy maintainers are not responsible for bugs in customized SELinux policies.}} | |||
= | = Independent SELinux Policy = | ||
While considering custom product policy, a product maintainer has two options: | |||
* Write his own SELinux policy from scratch and ask SELinux team for policy review. Note that a guide how to write an SELinux policy from scratch is not a part of this chapter (See <code>sepolicy generate</code> tool). | |||
* Extract an SELinux policy from a distribution policy package. The Git repository with distribution policies is located on https://github.com/fedora-selinux/selinux-policy%5Bgithub.com/fedora-selinux/selinux-policy and https://github.com/fedora-selinux/selinux-policy-contrib. | |||
{{admon/important|License|Distribution policies have GPL license, so any policy extracted from Distribution policy must have a GPL compatible license.}} | |||
= | = Agreement workflow = | ||
Before you start with shipping custom product policies, let the SELinux team know about your intentions. To do this, use SELinux Fedora mailing list or contact SELinux policy maintainer: | |||
* [mailto:selinux-policy-owner@fedoraproject.org SELinux Policy maintainer] | |||
* [mailto:selinux@lists.fedoraproject.org selinux@lists.fedoraproject.org] | |||
= Preparing sources for the Policy repository = | |||
It is recommended to create a Git repository for the SELinux policy sources. | |||
Corresponding policy module can than be extracted from [https://github.com/fedora-selinux/selinux-policy-contrib selinux-policy-contrib repository]. If there is no policy for the product, new policy should be created in this step and added to the repository. | |||
When the custom policy is ready, the product maintainer should create a build script (e.g. Makefile), attach a license file and make sure the policy compiles properly. | |||
== License == | == License == | ||
A Git repository should not contain only SELinux policy source files, but also a <code>license</code>. For more information how to add an open source license in your repository, see the [https://help.github.com/articles/adding-a-license-to-a-repository/ Adding a license to a repository] article on the GitHub Help. Distribution policies have GPL license, so any policy extracted from Distribution policy must have GPL compatible license. | A Git repository should not contain only SELinux policy source files, but also a <code>license</code>. For more information how to add an open source license in your repository, see the [https://help.github.com/articles/adding-a-license-to-a-repository/ Adding a license to a repository] article on the GitHub Help. Distribution policies have GPL license, so any policy extracted from Distribution policy must have a GPL compatible license. | ||
== Makefile == | == Makefile == | ||
To compile a product policy, you | To compile a product policy, you can use a <code>makefile</code>, for example (automatically generated by <code>sepolicy generate</code>): | ||
<pre>TARGET?=myapp | <pre>TARGET?=myapp | ||
Line 83: | Line 72: | ||
install: man | install: man | ||
install -D -m 644 ${TARGET}.pp.bz2 ${DESTDIR}${SHAREDIR}/selinux/packages/${TARGET}.pp.bz2 | install -D -m 644 ${TARGET}.pp.bz2 ${DESTDIR}${SHAREDIR}/selinux/packages/${TARGET}.pp.bz2 | ||
install -D -m 644 ${TARGET}_selinux.8 ${DESTDIR}${SHAREDIR}/man/man8/</pre> | install -D -m 644 ${TARGET}_selinux.8 ${DESTDIR}${SHAREDIR}/man/man8/</pre> | ||
{{ | If you choose not to use a Makefile, replace the <code>make</code> command in spec file with the following: | ||
<pre>make -f %{_datadir}/selinux/devel/Makefile %{modulename}.pp | |||
bzip2 -9 %{modulename}.pp</pre> | |||
== Policy source examples == | == Policy source examples == | ||
Line 94: | Line 85: | ||
<pre>$ cat myapp.te | <pre>$ cat myapp.te | ||
policy_module(myapp,1.0) | policy_module(myapp,1.0) | ||
type myapp_t; | type myapp_t; | ||
type myapp_exec_t; | type myapp_exec_t; | ||
init_daemon_domain(myapp_t, myapp_exec_t) | init_daemon_domain(myapp_t, myapp_exec_t) | ||
# Grant myapp_t the signal privilege | # Grant myapp_t the signal privilege | ||
allow myapp_t self:process { signal }; | allow myapp_t self:process { signal }; | ||
$ cat myapp.fc | $ cat myapp.fc | ||
/sbin/myapp -- gen_context(system_u:object_r:myapp_exec_t,s0) | /sbin/myapp -- gen_context(system_u:object_r:myapp_exec_t,s0) | ||
$ cat myapp.if | $ cat myapp.if | ||
## | ## | ||
My app service.</pre> | My app service.</pre> | ||
The SELinux policy Git repository should contain the following files (replace myapp with a name of your product): | The SELinux policy Git repository should contain the following files (replace myapp with a name of your product): | ||
<pre>$ ls | <pre>$ ls | ||
Makefile myapp.fc myapp.if myapp.te | Makefile myapp.fc myapp.if myapp.te COPYING</pre> | ||
== Compiling custom policy == | == Compiling custom policy == | ||
To compile | To compile finished policy, use the <code>make</code> command: | ||
<pre>$ make | <pre>$ make | ||
Line 135: | Line 121: | ||
Compressing myapp.pp -> myapp.pp.bz2 | Compressing myapp.pp -> myapp.pp.bz2 | ||
bzip2 -9 myapp.pp</pre> | bzip2 -9 myapp.pp</pre> | ||
After a succesful compilation, make an archive containing your policy: | After a succesful compilation, make an archive containing your policy: | ||
<pre>$ cd ../ | <pre>$ cd ../ | ||
$ tar -czf myapp-selinux.tar.gz myapp-selinux/</pre> | $ tar -czf myapp-selinux.tar.gz myapp-selinux/</pre> | ||
== Using custom interfaces == | == Using custom interfaces == | ||
{{admon/warning|Custom interface naming|All custom interfaces ''must'' be prefixed with "ipp_" not to be confused with distribution interfaces.}} | |||
The interface file of the custom policy module is '''not''' installed in the system because it would conflict with the interface file of the distribution module. Therefore any changes to it will not have effect on other policy modules. In order to use custom interfaces it is necessary to create new interface file with unique name (''ipp-[modulename].if'') and include it in the new package as follows: | |||
<pre>%install | |||
install -D -p -m 644 ipp-%{modulename}.if %{buildroot}%{_datadir}/selinux/devel/include/%{moduletype} | |||
%files | |||
%{_datadir}/selinux/devel/include/%{moduletype}/ipp-%{modulename}.if</pre> | |||
All custom interfaces ''must'' be prefixed with "ipp_" not to be confused with distribution interfaces. | |||
Changes to interfaces of the original module can only be delivered via distribution selinux-policy-* packages. If such a change is necessary, please contact the SELinux team, or submit a pull request. Please bear in mind that such changes will influence other policy modules that use given interface. | |||
== Custom policy modules and distribution policy == | |||
It’s important to note that distribution policies ''should not'' use interfaces from removable policy modules. | |||
When using types from custom policy modules ''stub'' interfaces should be used instead of directly requiring given type. Stub interface is defined and used in distribution module as follows. | |||
<pre>$ cat distribution_module.if | <pre>$ cat distribution_module.if | ||
Line 168: | Line 174: | ||
... | ... | ||
optional_policy(` | optional_policy(` | ||
distro_stub() | |||
allow distro_t myapp_log_t:file read_file_perms; | allow distro_t myapp_log_t:file read_file_perms; | ||
') | ') | ||
... | ... | ||
... | ...</pre> | ||
As with any type defined outside of ''SELinux policy base modules'', ''optional_policy'' block must be used when using types from removable modules in distribution policy. | |||
= Creating the Spec File = | = Creating the Spec File = | ||
Line 184: | Line 192: | ||
<pre># defining macros needed by SELinux | <pre># defining macros needed by SELinux | ||
%global selinuxtype targeted | %global selinuxtype targeted | ||
%global moduletype contrib | %global moduletype contrib | ||
%global modulename myapp</pre> | %global modulename myapp</pre> | ||
Then it is necessary to fill in all the information about the subpackage such as a name, a version, a license, and so on. | Then it is necessary to fill in all the information about the subpackage such as a name, a version, a license, and so on. | ||
Line 196: | Line 204: | ||
Summary: SELinux policies for product | Summary: SELinux policies for product | ||
Source0: # archive with SELinux policy sources. e.g: myapp-selinux.tar | Source0: # archive with SELinux policy sources. e.g: myapp-selinux.tar | ||
BuildRequires: selinux-policy | BuildRequires: selinux-policy | ||
BuildRequires: selinux-policy-devel | BuildRequires: selinux-policy-devel | ||
BuildArch: noarch | |||
%{?selinux_requires} | |||
%description | %description | ||
SELinux policy modules for product.</pre> | SELinux policy modules for product.</pre> | ||
= The %prep and %install Section = | |||
The following part of the .spec file describes the way a product policy is compiled and installed: | The following part of the .spec file describes the way a product policy is compiled and installed: | ||
Line 228: | Line 226: | ||
%install | %install | ||
# install policy modules | # install policy modules | ||
install -d %{buildroot}%{_datadir}/selinux/packages | install -d %{buildroot}%{_datadir}/selinux/packages/%{selinuxtype} | ||
install -m 0644 %{modulename}.pp.bz2 %{buildroot}%{_datadir}/selinux/packages/%{selinuxtype} | |||
install -m 0644 %{modulename}.pp.bz2 %{buildroot}%{_datadir}/selinux/packages | |||
%check</pre> | %check</pre> | ||
After this step, a product policy is installed on your system. | After this step, a product policy is installed on your system. | ||
Line 241: | Line 238: | ||
<pre>%post | <pre>%post | ||
%selinux_modules_install -s %{selinuxtype} %{_datadir}/selinux/packages/%{modulename}.pp.bz2 | %selinux_modules_install -s %{selinuxtype} %{_datadir}/selinux/packages/%{selinuxtype}/%{modulename}.pp.bz2 | ||
%postun | %postun | ||
Line 249: | Line 246: | ||
%posttrans | %posttrans | ||
%selinux_relabel_post -s %{selinuxtype} | %selinux_relabel_post -s %{selinuxtype}</pre> | ||
</pre> | |||
== The %files Section == | == The %files Section == | ||
The end of the .spec file contains the <code>%files</code> section. This section declares which files and directories are owned by the package. | The end of the .spec file contains the <code>%files</code> section. This section declares which files and directories are owned by the package. The last part of the spec file is changelog. | ||
<pre>%files | <pre>%files | ||
%{_datadir}/selinux/packages/%{modulename}.pp.bz2 | |||
%ghost %{_sharedstatedir}/selinux/%{selinuxtype}/active/modules/200/%{modulename} | |||
% | %license COPYING | ||
%changelog | %changelog | ||
* Mon Jan 01 2017 Author Name <Author@mail-example.com> - 0.1.0-1 | * Mon Jan 01 2017 Author Name <Author@mail-example.com> - 0.1.0-1 | ||
- First Build</pre> | - First Build</pre> | ||
== Adding dependency to the spec file of corresponding package == | |||
The *-selinux package should only be required on SELinux enabled systems. Therefore the following rich dependency syntax should be used: | |||
<pre>Requires: (%{name}-selinux if selinux-policy-%{selinuxtype})</pre> | |||
This ensures that the *-selinux package and all its dependencies are not pulled into containers and other systems that do not use SELinux. | |||
== SELinux Policy module priorities == | |||
Policy modules can be installed with different priorities. When multiple modules of the same name exist in the system, only the module with the highest priority takes effect. | |||
Distribution policy modules are installed with priority of 100. Custom policy should always be shipped with priority of 200 to override distribution policy. This value is contained inside the ''selinux_modules_install'' macro and should not be changed. | |||
Note that ''semodule'' installs policy modules with priority of 400 by default. | |||
See [https://plautrba.fedorapeople.org/selinux-modules-and-priority.html SELinux modules and priority] for more details about module priority. | |||
= Building a Package with an SELinux Product Policy = | = Building a Package with an SELinux Product Policy = | ||
== Setting Booleans During an Product Policy Installation == | == Setting Booleans During an Product Policy Installation == | ||
In some cases, it is | In some cases, it is necessary to enable or disable some booleans defined in a system security policy. This change should be done during the installation phase of the SELinux product package and it should also follow a couple of rules. | ||
{{admon/warning|Warning!|Setting | {{admon/warning|Warning!|Setting generic booleans can open security holes in the system.}} | ||
To change system booleans, use the following steps: | To change system booleans, use the following steps: | ||
Line 276: | Line 292: | ||
<li><p>Find a boolean that fits your needs best. Try to avoid generic booleans, which allow many things and their change could bring security holes to the system.</p></li> | <li><p>Find a boolean that fits your needs best. Try to avoid generic booleans, which allow many things and their change could bring security holes to the system.</p></li> | ||
<li><p>Specify booleans in the following format in the .spec file:</p> | <li><p>Specify booleans in the following format in the .spec file:</p> | ||
<pre># default boolean values need to be changed due to product policy | <pre># default boolean values need to be changed due to product policy | ||
# the change is performed by "%selinux_set_booleans" macro in %post phase | # the change is performed by "%selinux_set_booleans" macro in %post phase | ||
%global selinuxbooleans booleanname=1 booleanname2=0 | %global selinuxbooleans booleanname=1 booleanname2=0</pre> | ||
<li><p>It is necessary to use special macro _%selinux_set_booleans during "%post" phase of rpmbuild to make sure that the specified boolean values are set.</p></li></ul> | |||
See the following example: | |||
<li><p>It is necessary to use special macro | |||
<pre>%post | <pre>%post | ||
%selinux_modules_install -s %{selinuxtype} %{_datadir}/selinux/packages/%{modulename}.pp.bz2 | %selinux_modules_install -s %{selinuxtype} %{_datadir}/selinux/packages/%{selinuxtype}/%{modulename}.pp.bz2 | ||
%selinux_set_booleans -s %{selinuxtype} %{selinuxbooleans} | %selinux_set_booleans -s %{selinuxtype} %{selinuxbooleans} | ||
%postun | %postun | ||
%selinux_modules_uninstall -s %{selinuxtype} %{modulename} | %selinux_modules_uninstall -s %{selinuxtype} %{modulename} | ||
%selinux_unset_booleans -s %{selinuxtype} %{selinuxbooleans} | %selinux_unset_booleans -s %{selinuxtype} %{selinuxbooleans}</pre> | ||
The boolean macros mentioned above behave as follows: | |||
* | * The value of each boolean set using "%selinux_set_booleans" is recorded and will be reset to the original value when "%selinux_unset_booleans" is called | ||
* Number of calls to "%selinux_set_booleans" and "%selinux_unset_booleans" has to match in order for this mechanism to work properly | |||
== Port Labeling == | == Port Labeling == | ||
Line 305: | Line 318: | ||
If your product policy does not define port labels (such as "product_port_t"), you can skip this section. | If your product policy does not define port labels (such as "product_port_t"), you can skip this section. | ||
You should assign a port number and a port type | You should assign a port number and a port type to every port label. Assigning a port label should be done in %post install phase. For example, for the TCP 1111 port, the <code>semanage port -a -t product_port_t -p tcp 1111</code> command should be added to the if statement in the .spec file: | ||
<pre>if %{_sbindir}/selinuxenabled ; then | <pre>if %{_sbindir}/selinuxenabled ; then | ||
%{_sbindir}/semanage port -a -t product_port_t -p tcp 1111 | %{_sbindir}/semanage port -a -t product_port_t -p tcp 1111 | ||
fi</pre> | fi</pre> | ||
Where the <code>a</code>, <code>t</code>, and <code>p</code> of the <code>semanage</code> command mean the following: | Where the <code>a</code>, <code>t</code>, and <code>p</code> of the <code>semanage</code> command mean the following: | ||
<pre>-a Add a record of the specified object type | <pre>-a Add a record of the specified object type | ||
-t SELinux type for the | -t SELinux type for the port | ||
-p Protocol for the specified port (tcp|udp)</pre> | -p Protocol for the specified port (tcp|udp)</pre> | ||
For the %post uninstall phase, the port assignment should be removed. To do this, add the <code>semanage port -d -t <PORT></code> command in your .spec file | |||
For the %post uninstall phase, the port assignment should be removed. To do this, add the <code>semanage port -d -t <PORT></code> command in your .spec file. For example: | |||
<pre>if %{_sbindir}/selinuxenabled ; then | <pre>if %{_sbindir}/selinuxenabled ; then | ||
%{_sbindir}/semanage port -d -p tcp -t product_port_t | %{_sbindir}/semanage port -d -p tcp -t product_port_t | ||
fi</pre> | fi</pre> | ||
= Removing | = Removing your Product Policy from the System Policy = | ||
When | When your own product SELinux subpackage is ready for a release, contact the SELinux policy maintainer. He should remove the product policy from the SELinux distribution policy and update the package. You should then add a dependency on the new selinux-policy package: | ||
<pre># Version of selinux-policy when product policy was removed | <pre># Version of selinux-policy when product policy was removed | ||
%global selinux_policyver POLICY_VERSION | %global selinux_policyver POLICY_VERSION | ||
Requires: selinux-policy >= %{selinux_policyver}</pre> | Requires: selinux-policy >= %{selinux_policyver}</pre> | ||
If the released policy was not part of the distribution policy, there is no need to add a version dependency to your .spec file. | |||
Now your SELinux subpackage is ready for release. It is recommended to create a group update together with selinux-policy package to ensure that the updating process will be successful. | |||
=== SELinux in general | = Resources = | ||
== SELinux in general == | |||
* https://docs.fedoraproject.org/en-US/Fedora/25/html/SELinux_Users_and_Administrators_Guide/index.html | * https://docs.fedoraproject.org/en-US/Fedora/25/html/SELinux_Users_and_Administrators_Guide/index.html | ||
* https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/7/html/SELinux_Users_and_Administrators_Guide/ | |||
* https://mgrepl.wordpress.com/2016/11/01/selinux-security-policy-part1-is-it-a-magic/ | * https://mgrepl.wordpress.com/2016/11/01/selinux-security-policy-part1-is-it-a-magic/ | ||
* https://mgrepl.wordpress.com/2016/11/29/selinux-security-policy-part2-labels/ | * https://mgrepl.wordpress.com/2016/11/29/selinux-security-policy-part2-labels/ | ||
* https://mgrepl.wordpress.com/2016/12/13/selinux-security-policy-part-3-lables-in-action/ | * https://mgrepl.wordpress.com/2016/12/13/selinux-security-policy-part-3-lables-in-action/ | ||
== Why is SELinux useful == | |||
* https://lvrabec-selinux.rhcloud.com/wp-content/uploads/2016/08/slides-deck-6-7-9.html#/ | |||
* http://danwalsh.livejournal.com/71396.html | * http://danwalsh.livejournal.com/71396.html | ||
* https://www.youtube.com/watch?v=Ysshrh4aGOs&t=3s | * https://www.youtube.com/watch?v=Ysshrh4aGOs&t=3s | ||
* http://lvrabec-selinux.rhcloud.com/wp-content/uploads/2016/11/openAlt_proactive_security.pdf | |||
* http://lvrabec-selinux.rhcloud.com/wp-content/uploads/2016/11/LinuxDays.pdf | |||
* https://mgrepl.wordpress.com/2015/11/04/cve-2015-5602-and-selinux/ | * https://mgrepl.wordpress.com/2015/11/04/cve-2015-5602-and-selinux/ | ||
Latest revision as of 13:45, 17 May 2023
Creating Own Product Policies
In Fedora, there is a lot of applications and daemons which require customized SELinux security policy. The former approach with providing all policies only as a part of the system has been enhanced by the option to create custom product policy.
With the possibility to create custom product policy, required changes in a policy can be released immediately, so the product package maintainer does not need to wait for another SELinux policy package release. In other words, a product SELinux policy is always synchronized with the corresponding product (package).
This chapter is dedicated to shipping custom SELinux security module as a subpackage for a daemon or an application.
Independent SELinux Policy
While considering custom product policy, a product maintainer has two options:
- Write his own SELinux policy from scratch and ask SELinux team for policy review. Note that a guide how to write an SELinux policy from scratch is not a part of this chapter (See
sepolicy generate
tool). - Extract an SELinux policy from a distribution policy package. The Git repository with distribution policies is located on https://github.com/fedora-selinux/selinux-policy%5Bgithub.com/fedora-selinux/selinux-policy and https://github.com/fedora-selinux/selinux-policy-contrib.
Agreement workflow
Before you start with shipping custom product policies, let the SELinux team know about your intentions. To do this, use SELinux Fedora mailing list or contact SELinux policy maintainer:
Preparing sources for the Policy repository
It is recommended to create a Git repository for the SELinux policy sources.
Corresponding policy module can than be extracted from selinux-policy-contrib repository. If there is no policy for the product, new policy should be created in this step and added to the repository.
When the custom policy is ready, the product maintainer should create a build script (e.g. Makefile), attach a license file and make sure the policy compiles properly.
License
A Git repository should not contain only SELinux policy source files, but also a license
. For more information how to add an open source license in your repository, see the Adding a license to a repository article on the GitHub Help. Distribution policies have GPL license, so any policy extracted from Distribution policy must have a GPL compatible license.
Makefile
To compile a product policy, you can use a makefile
, for example (automatically generated by sepolicy generate
):
TARGET?=myapp MODULES?=${TARGET:=.pp.bz2} SHAREDIR?=/usr/share all: ${TARGET:=.pp.bz2} %.pp.bz2: %.pp @echo Compressing $^ -\> $@ bzip2 -9 $^ %.pp: %.te make -f ${SHAREDIR}/selinux/devel/Makefile $@ clean: rm -f *~ *.tc *.pp *.pp.bz2 rm -rf tmp *.tar.gz man: install-policy sepolicy manpage --path . --domain ${TARGET}_t install-policy: all semodule -i ${TARGET}.pp.bz2 install: man install -D -m 644 ${TARGET}.pp.bz2 ${DESTDIR}${SHAREDIR}/selinux/packages/${TARGET}.pp.bz2 install -D -m 644 ${TARGET}_selinux.8 ${DESTDIR}${SHAREDIR}/man/man8/
If you choose not to use a Makefile, replace the make
command in spec file with the following:
make -f %{_datadir}/selinux/devel/Makefile %{modulename}.pp bzip2 -9 %{modulename}.pp
Policy source examples
For the purpose of this example, we create a policy named myapp:
$ cat myapp.te policy_module(myapp,1.0) type myapp_t; type myapp_exec_t; init_daemon_domain(myapp_t, myapp_exec_t) # Grant myapp_t the signal privilege allow myapp_t self:process { signal }; $ cat myapp.fc /sbin/myapp -- gen_context(system_u:object_r:myapp_exec_t,s0) $ cat myapp.if ## My app service.
The SELinux policy Git repository should contain the following files (replace myapp with a name of your product):
$ ls Makefile myapp.fc myapp.if myapp.te COPYING
Compiling custom policy
To compile finished policy, use the make
command:
$ make make -f /usr/share/selinux/devel/Makefile myapp.pp make[1]: Entering directory '/home/lvrabec/devel/documentations/examples' Compiling targeted myapp module /usr/bin/checkmodule: loading policy configuration from tmp/myapp.tmp /usr/bin/checkmodule: policy configuration loaded /usr/bin/checkmodule: writing binary representation (version 17) to tmp/myapp.mod Creating targeted myapp.pp policy package rm tmp/myapp.mod.fc tmp/myapp.mod make[1]: Leaving directory '/home/lvrabec/devel/documentations/examples' Compressing myapp.pp -> myapp.pp.bz2 bzip2 -9 myapp.pp
After a succesful compilation, make an archive containing your policy:
$ cd ../ $ tar -czf myapp-selinux.tar.gz myapp-selinux/
Using custom interfaces
The interface file of the custom policy module is not installed in the system because it would conflict with the interface file of the distribution module. Therefore any changes to it will not have effect on other policy modules. In order to use custom interfaces it is necessary to create new interface file with unique name (ipp-[modulename].if) and include it in the new package as follows:
%install install -D -p -m 644 ipp-%{modulename}.if %{buildroot}%{_datadir}/selinux/devel/include/%{moduletype} %files %{_datadir}/selinux/devel/include/%{moduletype}/ipp-%{modulename}.if
All custom interfaces must be prefixed with "ipp_" not to be confused with distribution interfaces.
Changes to interfaces of the original module can only be delivered via distribution selinux-policy-* packages. If such a change is necessary, please contact the SELinux team, or submit a pull request. Please bear in mind that such changes will influence other policy modules that use given interface.
Custom policy modules and distribution policy
It’s important to note that distribution policies should not use interfaces from removable policy modules.
When using types from custom policy modules stub interfaces should be used instead of directly requiring given type. Stub interface is defined and used in distribution module as follows.
$ cat distribution_module.if ... ... ######################################## ## <summary> ## DBUS stub interface. No access allowed. ## </summary> ## <param name="domain" unused="true"> ## <summary> ## Domain allowed access ## </summary> ## </param> # interface(`distro_stub',` gen_require(` type dystro_t; ') ') ... ... $ cat myapp.te ... ... optional_policy(` distro_stub() allow distro_t myapp_log_t:file read_file_perms; ') ... ...
As with any type defined outside of SELinux policy base modules, optional_policy block must be used when using types from removable modules in distribution policy.
Creating the Spec File
When a Git repository with SELinux policy sources is ready, create your product .spec file (rpmbuild configuration file).
The Preamble
First of all an SELinux policy type, a module type, and a module name should be defined:
# defining macros needed by SELinux %global selinuxtype targeted %global moduletype contrib %global modulename myapp
Then it is necessary to fill in all the information about the subpackage such as a name, a version, a license, and so on.
Name: myapp-selinux Version: 1.0 Release: 1%{?dist} License: GPLv2 URL: # URL to git repository with policy source files Summary: SELinux policies for product Source0: # archive with SELinux policy sources. e.g: myapp-selinux.tar BuildRequires: selinux-policy BuildRequires: selinux-policy-devel BuildArch: noarch %{?selinux_requires} %description SELinux policy modules for product.
The %prep and %install Section
The following part of the .spec file describes the way a product policy is compiled and installed:
%prep %setup -q %build make %pre %selinux_relabel_pre -s %{selinuxtype} %install # install policy modules install -d %{buildroot}%{_datadir}/selinux/packages/%{selinuxtype} install -m 0644 %{modulename}.pp.bz2 %{buildroot}%{_datadir}/selinux/packages/%{selinuxtype} %check
After this step, a product policy is installed on your system.
The %post Section
Next step is loading a product policy into the kernel in the RPM post-install process. This step also contains the post-uninstall process to remove a product policy properly during a product uninstallation.
%post %selinux_modules_install -s %{selinuxtype} %{_datadir}/selinux/packages/%{selinuxtype}/%{modulename}.pp.bz2 %postun if [ $1 -eq 0 ]; then %selinux_modules_uninstall -s %{selinuxtype} %{modulename} fi %posttrans %selinux_relabel_post -s %{selinuxtype}
The %files Section
The end of the .spec file contains the %files
section. This section declares which files and directories are owned by the package. The last part of the spec file is changelog.
%files %{_datadir}/selinux/packages/%{modulename}.pp.bz2 %ghost %{_sharedstatedir}/selinux/%{selinuxtype}/active/modules/200/%{modulename} %license COPYING %changelog * Mon Jan 01 2017 Author Name <Author@mail-example.com> - 0.1.0-1 - First Build
Adding dependency to the spec file of corresponding package
The *-selinux package should only be required on SELinux enabled systems. Therefore the following rich dependency syntax should be used:
Requires: (%{name}-selinux if selinux-policy-%{selinuxtype})
This ensures that the *-selinux package and all its dependencies are not pulled into containers and other systems that do not use SELinux.
SELinux Policy module priorities
Policy modules can be installed with different priorities. When multiple modules of the same name exist in the system, only the module with the highest priority takes effect.
Distribution policy modules are installed with priority of 100. Custom policy should always be shipped with priority of 200 to override distribution policy. This value is contained inside the selinux_modules_install macro and should not be changed.
Note that semodule installs policy modules with priority of 400 by default.
See SELinux modules and priority for more details about module priority.
Building a Package with an SELinux Product Policy
Setting Booleans During an Product Policy Installation
In some cases, it is necessary to enable or disable some booleans defined in a system security policy. This change should be done during the installation phase of the SELinux product package and it should also follow a couple of rules.
To change system booleans, use the following steps:
Find a boolean that fits your needs best. Try to avoid generic booleans, which allow many things and their change could bring security holes to the system.
Specify booleans in the following format in the .spec file:
# default boolean values need to be changed due to product policy # the change is performed by "%selinux_set_booleans" macro in %post phase %global selinuxbooleans booleanname=1 booleanname2=0
It is necessary to use special macro _%selinux_set_booleans during "%post" phase of rpmbuild to make sure that the specified boolean values are set.
See the following example:
%post %selinux_modules_install -s %{selinuxtype} %{_datadir}/selinux/packages/%{selinuxtype}/%{modulename}.pp.bz2 %selinux_set_booleans -s %{selinuxtype} %{selinuxbooleans} %postun %selinux_modules_uninstall -s %{selinuxtype} %{modulename} %selinux_unset_booleans -s %{selinuxtype} %{selinuxbooleans}
The boolean macros mentioned above behave as follows:
- The value of each boolean set using "%selinux_set_booleans" is recorded and will be reset to the original value when "%selinux_unset_booleans" is called
- Number of calls to "%selinux_set_booleans" and "%selinux_unset_booleans" has to match in order for this mechanism to work properly
Port Labeling
If your product policy does not define port labels (such as "product_port_t"), you can skip this section.
You should assign a port number and a port type to every port label. Assigning a port label should be done in %post install phase. For example, for the TCP 1111 port, the semanage port -a -t product_port_t -p tcp 1111
command should be added to the if statement in the .spec file:
if %{_sbindir}/selinuxenabled ; then %{_sbindir}/semanage port -a -t product_port_t -p tcp 1111 fi
Where the a
, t
, and p
of the semanage
command mean the following:
-a Add a record of the specified object type -t SELinux type for the port -p Protocol for the specified port (tcp|udp)
For the %post uninstall phase, the port assignment should be removed. To do this, add the semanage port -d -t <PORT>
command in your .spec file. For example:
if %{_sbindir}/selinuxenabled ; then %{_sbindir}/semanage port -d -p tcp -t product_port_t fi
Removing your Product Policy from the System Policy
When your own product SELinux subpackage is ready for a release, contact the SELinux policy maintainer. He should remove the product policy from the SELinux distribution policy and update the package. You should then add a dependency on the new selinux-policy package:
# Version of selinux-policy when product policy was removed %global selinux_policyver POLICY_VERSION Requires: selinux-policy >= %{selinux_policyver}
If the released policy was not part of the distribution policy, there is no need to add a version dependency to your .spec file.
Now your SELinux subpackage is ready for release. It is recommended to create a group update together with selinux-policy package to ensure that the updating process will be successful.
Resources
SELinux in general
- https://docs.fedoraproject.org/en-US/Fedora/25/html/SELinux_Users_and_Administrators_Guide/index.html
- https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/7/html/SELinux_Users_and_Administrators_Guide/
- https://mgrepl.wordpress.com/2016/11/01/selinux-security-policy-part1-is-it-a-magic/
- https://mgrepl.wordpress.com/2016/11/29/selinux-security-policy-part2-labels/
- https://mgrepl.wordpress.com/2016/12/13/selinux-security-policy-part-3-lables-in-action/
Why is SELinux useful
- https://lvrabec-selinux.rhcloud.com/wp-content/uploads/2016/08/slides-deck-6-7-9.html#/
- http://danwalsh.livejournal.com/71396.html
- https://www.youtube.com/watch?v=Ysshrh4aGOs&t=3s
- http://lvrabec-selinux.rhcloud.com/wp-content/uploads/2016/11/openAlt_proactive_security.pdf
- http://lvrabec-selinux.rhcloud.com/wp-content/uploads/2016/11/LinuxDays.pdf
- https://mgrepl.wordpress.com/2015/11/04/cve-2015-5602-and-selinux/