When should you use the “optional_policy” block statement?
After writing the blog on optional policy, I received the following question:
“Ho do I know whether I need to use the optional_policy block or not?”
When we write policy we can choose to have the policy either shipped within the base policy or as as module.
We use the modules config files to specify whether a policy is in the base or module.
We have a different modules config file for each policy type that we ship
which contain statements like
# Layer: kernel
# Module: domain
# Required in base
# Core policy for domains.
domain = base
# Layer: system
# Module: init
# System initialization programs (init and init scripts).
init = module
What does either “base” or “module” mean? The note says
# For modular policies, modules set to “base” will be
# included in the base module. “module” will be compiled
# as individual loadable modules.
The base.pp policy module contains core policy modules which are needed for the basic confinement of your system focused on the core operating system. The base.pp module can not be removed from your policy.
But what about “module”. This is different. Theoretically these modules are all optional. Meaning you should be able to remove them from the policy if you wanted to.
You can list the modules using:
$ semodule -l
There are some exceptions for modules like miscfiles, authlogin, init,
systemd, sysnetwork. We define them as “module” in the modules-*.conf
file but they can not be removed.
Another way of looking at this would be to examine the directories in
which we ship the interfaces. We ship interface files in /usr/share/selinux/devel/include/ subdirs
system kernel roles services admin apps
Interfaces in system and kernel are core to the system, while interfaces in the other directories as optional.
Let’s say you write a policy and you need to use a rpm interface because your application execute rpm -qi. First, we need to examine that the rpm module is not a part of the base.pp policy module
$ semodule -l | grep rpm
Ok, I see it is not. So I will call a rpm interface with the optional_policy block.