Handling of SELinux in Distros Allowing for Controlled Updates and Local Policies

The current modus operandus of policies as distributed by distros lumps all the policy into one big package. This results in any local policy modifications being wiped away whenever the distro pushes an update to policy. A more ideal situation is to have per module policy packages and a local policy config that allow for per module updates and local policy overrides. Read More

The Evils of Single Policy Packages

Well, straight away, there is a conceptual disconnect. Almost every policy these days is a modular policy. It is broken out into separate and distinct modules that can be enabled or disabled through the use of semanage. Recombining the policy back into a single package is counter-productive and removes some of the potential benefits of having modular policy.

Ignoring, for a moment, the fact that policy is already broken out into distinct policy modules (often associated to a single application/service). There is the problem of policy _upgrades_. Whenever a policy needs to be upgraded, the _entire_ policy must be changed. This becomes particularly nasty when a security fix has been found for an application, apache for example. You want to install the new policy for apache, but you don't want to update your cron policy. There are a number of reasons why you wouldn't want to upgrade your cron policy. Perhaps the new cron policy breaks your usage of cron. More likely though, is that you've created a custom cron policy and upgrading the policy as a whole will clobber this policy (replacing it with the distro's cron policy).

Consider the following upgrade scenario:

You have an older, more stable, version of application X installed with the security policy S. A newer version of another application, Y+1, is available and some kind person creates an updated security policy, S+1, for it. Lets also say that a newer version of application X with some additional features is available, X+1, and the policy S+1 give the application the broader access it needs for those new features.

This is where things get nasty. Let's say that application Y has a security vulnerability and _must_ be upgraded to Y+1. What can you do?

If you upgrade application Y to Y+1, you'll also need to upgrade to security policy S+1. But if you do that, you'll be using application X with a security policy designed for application X+1. Being a strong advocate of Least Privilege this really rubs you the wrong way because S+1 gives application X too many privileges.

If you install S+1, then you'll have reduced the overall benefit of having a Mandatory Access Control policy in the first place. X will now be allowed to do things which it otherwise could _not_ have done, exposing you to a wider range of security threats.

You could keep your current version of application Y. But that's not really an option since it has a known vulnerability.

As a last resort you could create a custom policy. If you do this though you will have essentially created a branch of the upstream security policy and you will get all the joys that branching entails (including, merging future policy updates, tracking upstream yourself, manually rebuilding the policy, managing an repository of your own, etc.)

Consider the likelihood of either needing custom policy or fine-grained control over policy module version (and hence a custom single policy package). I suspect that this number is quiet high even for a fairly simple setup.

Per Policy Module Packages

If policies were packaged on a per policy module basis, the upgrade situation is much improved. The policies can be upgraded or replaced individually allowing for the scenario above to be handled sanely. You'll be able to happily keep your old, stable application X with its specific policy module S(X) and still be able to upgrade application Y and its policy S(Y) to Y+1 and S(Y+1).

Just such a system was designed for Ubuntu Hardy's SELinux support. In fact the system in Hardy is even better than that. By taking the advantage of modular policy, it is also able to account for local policy modules that either replace or augment upstream policy!

Local Policy

Remember from above, where you essentially had to branch the upstream policy to simultaneously support older and newer software? Well, having per policy modules makes that easy to do. How about the case where you have a completely different policy for an application? In this case what you really want is a way to sanely replace the upstream policy module without breaking future policy upgrades.

For example, if you have a directory, /etc/selinux.d, which contains policy modules, /etc/selinux.d/<policyname>/<module>.pp. Let's say that these modules are the ones that are loaded whenever a script is run to update the system policy, update-selinux-policy. Now lets say that the modules, /etc/selinux.d/<policyname>/<module>.pp, are sym links, /usr/share/selinux/<policyname>/<module>.pp, and that those are the policies installed by upstream.

How do you install your custom policy module? Simple! You just replace the sym link to the upstream policy module with your custom policy module and run update-selinux-policy.

;o} If you're running Ubuntu Hardy you are in luck! Because that is exactly how local policies are handled.

Notes:

As I've said earlier, the SELinux Ubuntu Hardy packages have this kind of setup. If you are interested in learning more, I recommend looking at the source packages for "selinux" and "refpolicy". In particular, you'll note that there are separate packages for the unconfined and cups modules (unfortunately not for any other packages just yet) and that there is indeed a script, update-selinux-policy, for handling local policy modules.

Comments

Ubuntu Developer

"Caleb Case is not an Ubuntu developer. He did some SE Linux package work that was sponsored into Ubuntu during a period with SE Linux in Debian was dormant, but since then we’ve rebased everything on Debian’s packages." -- Scott Kitterman

In the interest of full disclosure, I am not an official Ubuntu developer. I did contribute a large amount of work, at least I like to think so, to getting SELinux packages ready for Hardy. As Scott says, the Intrepid release will be, as far as I know, using different packages from Debian. Some of the concepts that were introduced in the Hardy SELinux packages may find their way into the Debian packages. It is my hope that many of the 'good' ones will. This post about policy packaging is directly related to that hope.

Russell Coker

Russell has been kind enough to comment on my post. You can find his thoughts and others on his blog.

Post new comment

The content of this field is kept private and will not be shown publicly.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Allowed HTML tags: <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd>
  • Lines and paragraphs break automatically.
  • You can enable syntax highlighting of source code with the following tags: <code>, <blockcode>. Beside the tag style "<foo>" it is also possible to use "[foo]".

More information about formatting options

CAPTCHA
Declare your humanity!
Image CAPTCHA
Copy the characters (respecting upper/lower case) from the image.