[Rpm-maint] [RFC] Packaging SELinux Policy in RPMs

Steve Lawrence slawrence at tresys.com
Thu Apr 1 20:45:33 UTC 2010

As discussed, we have decided to rewrite SELinux support in RPM to move
policy into their own 'policy packages', separate from the associated
application packages. With this change, we need to take another look at
the different ways policy can be packaged separately, and the pros and
cons of each approach.

The first approach is similar to what our previous patchset did, where
all policy types are stored in one 'policy package', though separate
from the application package. For example, this approach would have
these two packages: apache.rpm and apache-policy.rpm, with apache
containing the normal apache application and apache-policy containing
all types (mls, targeted, etc) for the apache module. This has a couple
advantages. Firstly, all policy is in a single package, meaning only one
rpm needs to be distributed to get all policies. Additionally,
dependencies are fairly straightforward. For example, apache.rpm would
Require apache-policy.rpm, and during installation, the correct policy
type would be extracted and installed based on the system policy type.

However, this method of policy packaging does have some side effects.
This method means all policy packages will always be installed, even if
SELinux is not installed. Similarly, all policy types will be on disk
even though only one type is active. This leads to an issue with
switching policy types. If we wanted to switch from the targeted to mls
policy type, for example, we would need a tool to extract and install
the mls policies from the currently installed policy packages. Also,
because we would use RPMs PRCO, you couldn't obsolete a single policy
type. You could only obsolete an entire policy package. It also means
you can't maintain packages for your custom policy separately (e.g.
foobar-apache-policy.rpm works with type foobar, while RH keeps
providing targeted, etc.). You'd instead have to override the upstream
policy packages with your own.

Rather than having a single policy package containing all policy types,
another option could have separate policy packages for all modules of
all types. For example, we might have apache-policy-targeted.rpm and
apache-policy-mls.rpm. This solves some of the previously mentioned
issues (e.g. obsoletes, policy type switching), but determining which
policy package to install must now be determined by Yum/RPMs dependency
solver/checker. There are a few ways to accomplish this, but none are

One method that could solve this is conditional requirements. For
example, something along these lines:

    Requires: selinux-policy-targeted ? apache-policy-targeted
    Requires: selinux-policy-mls ? apache-policy-mls

This would automatically require the correct policies based on the
currently installed base policies, and completely eliminates the type
switching issue. However, this may be difficult to implement and could
affect a lot of rpm dependency checking. This is further complicated if
real conditionals, such as else, not, and, or, and nested conditionals
are desired, though they shouldn't be needed for policy requirements.

A similar option, but perhaps not as difficult, would be to add runtime
macro expansion in Requires.  For example, you might have something like

    Requires: apache-policy-%{SELINUX_TYPE}

This gives similar results to conditional requirements. Unlike
conditionals though, dummy packages would be needed in the case where
SELinux isn't installed but something is needed to meet the
apache-policy-%{SELINUX_TYPE} dependency. This still suffers from the
policy switching problem as well.

Another option might have all apache-policy-* packages Provide
apache-policy, and apache would only require apache-policy.  However,
this would require that Yum/RPM  need some logic to pick the correct
apache-policy-X package. This also has the same need for dummy packages
and policy switching issues.

Another drawback with having all policy types in separate packages is
the loss of the 'default' type.  Previously, you could specify a module
as a 'default' type and it could be installed into the current policy,
no matter the type. With the separate packages, this becomes very
difficult to implement cleanly.

Each of these are possible solutions, each with pluses and minus. Do you
feel any of these are the completely wrong approach? Any possible
alternatives that we may have missed?

More information about the Rpm-maint mailing list