3

Ownership of the Local SE Linux Policy

A large part of the disagreement about the way to manage the policy seems to be based on who will be the primary “owner” of the policy on the machine. This isn’t a problem that only applies to SE Linux, the same issue applies for various types of configuration files and scripts throughout the process of distribution development. Having a range of modules which can be considered configuration data that come from a single source seems to make SE Linux policy unique among other packages. The reasons for packaging all Apache modules in the main package seem a lot clearer.

One idea that keeps cropping up is that as the policy is modular it should be included in daemon packages and the person maintaining the distribution package of the policy should maintain it. The reason for this request seems to usually be based on the idea that the person who packages a daemon for a distribution knows more about how it works than anyone else, I believe that this is false in most cases. When I started working on SE Linux I had a reasonable amount of experience in maintaining Debian packages of daemons and server processes, but I had to learn a lot about how things REALLY work to be able to write good policy. Also if we were to have policy modules included in the daemon packages, then those packages would need to be updated whenever there were serious changes to the SE Linux policy. For example Debian/Unstable flip-flopped on MCS support recently, changing the policy packages to re-enable MCS was enough pain, getting 50 daemon packages updated would have been unreasonably painful. Then of course there is the case where two daemons need to communicate, if the interface which is provided with one policy module has to be updated before another module can be updated and they are in separate packages then synchronised updates to two separate packages might be required for a single change to the upstream policy. I believe that the idea of having policy modules owned by the maintainers of the various daemon packages is not viable. I also believe that most people who package daemons would violently oppose the idea of having to package SE Linux policy if they realised what would be required of them.

Caleb Case seems to believe that ownership of policy can either be based on the distribution developer or the local sys-admin with apparently little middle-ground [1]. In the section titled “The Evils of Single Policy Packages” he suggests that if an application is upgraded for a security fix, and that upgrade requires a new policy, then it requires a new policy for the entire system if all the policy is in the same package. However the way things currently work is that upgrading a Debian SE Linux policy package does not install any of the new modules. They are stored under /usr/share/selinux/default but the active modules are under /etc/selinux/default/modules/active. An example of just such an upgrade is the Debian Security Advisory DSA-1617-1 for the SE Linux policy for Etch to address the recent BIND issue [2]. In summary the new version of BIND didn’t work well with the SE Linux policy, so an update was released to fix it. When the updated SE Linux policy package is installed it will upgrade the bind.pp module if the previous version of the package was known to have the version of bind.pp that didn’t allow named to bind() to most UDP ports – the other policy modules are not touched. I think that this is great evidence to show that the way things currently work in Debian work well. For the hypothetical case where a user had made local modifications to the bind.pp policy module, they could simply put the policy package on hold – I think it’s safe to assume that anyone who cares about security will read the changelogs for all updates to released versions of Debian, so they would realise the need to do this.

Part of Caleb’s argument rests on the supposed need for end users to modify policy packages (IE to build their own packages from modified source). I run many SE Linux machines, and since the release of the “modular” policy (which first appeared in Fedora Core 5, Debian/Etch, and Red Hat Enterprise Linux 5) I have never needed to make such a modification. I modify policy regularly for the benefit of Debian users and have a number of test machines to try it out. But for the machines where I am a sysadmin I just create a local module that permits the access that is needed. The only reason why someone would need to modify an existing module is to remove privileges or to change automatic domain transition rules. Changing automatic domain transitions is a serious change to the policy which is not something that a typical user would want to do – if they were to do such things then they would probably grab the policy source and rebuild all the policy packages. Removing privileges is not something that a typical sysadmin desires, the reference policy is reasonably strict and users generally don’t look for ways to tighten up the policy. In almost all cases it seems best to consider that the policy modules which are shipped by the distribution are owned by the distribution not the sysadmin. The sysadmin will decide which policy modules to load, what roles and levels to assign to users with the semanage tool, and what local additions to add to the policy. For the CentOS systems I run I use the Red Hat policy, I don’t believe that there is a benefit for me to change the policy that Red Hat ships, and I think that for people who have less knowledge about SE Linux policy than me there are more reasons not to change such policy and less reasons to do so.

Finally Caleb provides a suggestion for managing policy modules by having sym-links to the modules that you desire. Of course there is nothing preventing the existence of a postfix.pp file on the system provided by a package while there is a local postfix.pp file which is the target of the sym-link (so the sym-link idea does not support the idea of having multiple policy packages). With the way that policy modules can be loaded from any location, the only need for sym-links is if you want to have an automatic upgrade script that can be overridden for some modules. I have no objection to adding such a feature to the Debian policy packages if someone sends me a patch.

Caleb also failed to discuss how policy would be initially loaded if packaged on a per-module basis. If for example I had a package selinux-policy-default-postfix which contains the file postfix.pp, how would this package get installed? I am not aware of the Debian package dependencies (or those of any other distribution) being about to represent that the postfix package depends on selinux-policy-default-postfix if and only if the selinux-policy-default package is installed. Please note that I am not suggesting that we add support for such things, a package management system that can solve Sudoku based on package dependency rules is not something that I think would be useful or worth having. As I noted in my previous post about how to package SE Linux policy for distributions [3] the current Debian policy packages have code in the postinst (which I believe originated with Erich Schubert) to load policy modules that match the Debian packages on the system. This means that initially setting up the policy merely requires installing the selinux-policy-default package and rebooting. I am inclined to reject any proposed change which makes the initial install of of the policy more difficult than this.

After Debian/Lenny is released I plan to make some changes to the policy. One thing that I want to do is to have a Debconf option to allow users to choose to automatically upgrade their running policy whenever they upgrade the Debian policy package, this would probably only apply to changes within one release (IE it wouldn’t cause an automatic upgrade from Lenny+1 policy to Lenny+2). Another thing I would like to do is to have the policy modules which are currently copied to /etc/selinux/default/modules/active instead be hard linked when the source is a system directory. That would save about 12M of disk space on some of my systems.

I’ve taken the unusual step of writing two blog posts in response to Caleb’s post not because I want to criticise him (he has done a lot of good work), but because he is important in the SE Linux community and his post deserves the two hours I have spent writing responses to it. While writing these posts I have noticed a number of issues that can be improved, I invite suggestions from Caleb and others on how to make such improvements.

10

SE Linux Policy Packaging for a Distribution

Caleb Case (Ubuntu contributer and Tresys employee) has written about the benefits of using separate packages for SE Linux policy modules [1].

Firstly I think it’s useful to consider some other large packages that could be split into multiple packages. The first example that springs to mind is coreutils which used to be textutils, shellutils, and fileutils. Each of those packages contained many programs and could conceivably have been split. Some of the utilities in that package are replaced for most use, for example no-one uses the cksum utility, generally md5sum and sha1sum (which are in the same package) are used instead. Also the pinky command probably isn’t even known by most users who use finger instead (apart from newer Unix users who don’t even know what finger is). So in spite of the potential benefit of splitting the package (or maintaining the previous split) it was decided that it would be easier for everyone to have a single package. The merge of the three packages was performed upstream, but there was nothing preventing the Debian package maintainer from splitting the package – apart from the inconvenience to everyone. The coreutils package in Etch takes 10M of disk space when installed, as it’s almost impossible to buy a new hard drive smaller than 80G that doesn’t seem to be a problem for most users.

The second example is the X server which has separate packages for each video card. One thing to keep in mind about the X server is that the video drivers don’t change often. While it is quite possible to remove a hard drive from one machine and install it in another, or duplicate a hard drive to save the effort of a re-install (I have done both many times) they are not common operations in the life of a system. Of course when you do require such an update you need to first install the correct package (out of about 60 choices), which can be a challenge. I suspect that most Debian systems have all the video driver packages installed (along with drivers for wacom tablets and other hardware devices that might be used) as that appears to be the default. So it seems likely that a significant portion of the users have all the packages installed and therefore get no benefit from the split package.

Now let’s consider the disk space use of the selinux-policy-default package – it’s 24M when installed. Of that 4.9M is in the base.pp file (the core part of the policy which is required), then there’s 848K for the X server (which is going to be loaded on all Debian systems that have X clients installed – due to an issue with /tmp/.ICE-unix labelling [2]). Then there’s 784K for the Postfix policy (which is larger than it needs to be – I’ve been planning to fix this for the past four years or so) and 696K for the SSH policy (used by almost everyone). The next largest is 592K for the Unconfined policy, the number of people who choose not to use this will be small, and as it’s enabled by default it seems impractical to provide a way of removing it.

One possibility for splitting the policy is to create a separate package of modules used for the less common daemons and services, if modules for INN, Cyrus, distcc, ipsec, kerberos, ktalk, nis, PCMCIA, pcscd, RADIUS, rshd, SASL, and UUCP were in a separate package then that would reduce the installed size of the main package by 1.9M while providing no change in functionality to the majority of users.

One thing to keep in mind is that each package at a minimum will have a changelog and a copyright file (residing in a separate directory under /usr/share/doc) and three files as part of the dpkg data store, each of which takes up at least one allocation unit on disk (usually 4K). So adding one extra package will add at least 24K of disk space to every system that installs it (or 32K if the package has postinst and postrm scripts). This is actually a highly optimal case, the current policy packages (selinux-policy-default and selinux-policy-mls) each take 72K of disk space for their doc directory.

One of my SE Linux server sytems (randomly selected) has 23 policy modules installed, if they were in separate packages there would be a minimum of 552K of disk space used by packaging, 736K if there were postinst and postrm scripts, and as much as 2M if the doc directory for each package was similar to the current doc directories). As the system in question needs 5796K of policy modules, the 2M of overhead would make it approach 8M of disk space. So it would only be a saving of 16M over the current situation. While saving that amount of disk space is a good thing, I think that when balanced against the usability issues it’s not worth-while.

Currently the SE Linux policy packages will determine what applications are installed and automatically load policy packages to match. I don’t believe that it’s possible to have a package post-inst script install other packages (and if it is possible I don’t think it’s desirable). Therefore to have separate packages would make a significant difference to the ease of use, it seems that the best way to manage it would be to have the core policy package include a script to install the other packages.

Finally there’s the issue of when you recognise the need for a policy module. It’s not uncommon for me to do some work for a client while on a train, bus, or plane journey. I will grab packages needed to simulate a configuration that the client desires and then work out how to get it going correctly while on the journey. While it would not be a problem for me (I always have the SE Linux policy source and all packages on hand) I expect that many people who have similar needs might find themself a long way from net access without the policy package that they need to do their work. Sure such people could do their work in permissive mode, but that would encourage them to deploy in permissive mode too and thus defeat the goals of the SE Linux project (in terms of having wide-spread adoption).

My next post on this topic will cover the issue of custom policy.

Updated to note that Caleb is a contributor to Ubuntu not a developer.

2

Lenny SE Linux on the Desktop

I have been asked about the current status of Lenny SE Linux on the Desktop.

The first thing to consider is the combinations of policies and configurations. I will number them if only for the purpose of this post, if the numbering is considered generally helpful it could be more widely adopted to describe configurations.

  1. Default configuration. This has the default policy and is configured with all users having the domain unconfined_t and daemons such as POP servers are allowed to access home directories of type unconfined_home_dir_t. This allows such daemons to attack privileged user accounts.
  2. Some restricted users. This is the same as above but with some users restricted. Daemons such as POP servers are only allowed to access the home directories of restricted users. This means that if a user is to have an unconfined account and receive email they must have two Unix accounts or receive their mail under /var/spool/mail. This is one setsebool command and one (or maybe a few) “semanage login -m” commands from the default configuration.
  3. All users restricted. The system administrator has the domain sysadm_t and users have domains such as user_t. This requires a few more semanage commands. It is equivalent to the old strict policy.
  4. MLS. This is anything that is based around the MLS policy.

Currently I have two Desktop machines running Lenny (a test machine and my EeePC) and one server. I have only just switched my test machine to enforcing mode so have no good data on it (apart from the fact that I can boot it up and login – which is always a good start). The server is running in permissive mode because I have not yet written the policy to allow the POP server to read from unconfined_home_dir_t. I could get it working by switching from level 1 to level 2 or 3, but I want to get level 1 server policy working for the benefit of others else first.

My EeePC however is fully functional, I have been doing some work on it – that mostly means running a ssh client under GNOME but that’s OK (desktop environments such as GNOME and KDE are quite complex and demanding, getting a machine to boot and run such a desktop environment tests out many parts of the system). It’s only at level 1 for the moment because I want to get level 1 working everywhere before moving to the higher levels. I want to get things ready for real users ASAP. With the way the policy is managed now it will be possible to move from level 1 to 2 or 3 without rebooting or interrupting running services. So once users have systems running well at level 1 they can easily increase the security at a later date.

The problems that I have had are due to text relocations in libraries (see my previous post about execmod permission [1]). I’ve filed bug report #493678 against libtheora0 [2] in regard to this issue and included a patch from Fedora (which disables the non-relocatable assembly code in question). It seems that upstream have some new assembler code to try and fix this issue, so hopefully we’ll have something that can make it into Lenny!

I’ve filed bug report #493705 against libswscale0 for the same issue [3]. I included a patch to turn off the assembler code in question but that was not well received. If anyone has some i386 assembler skill and some spare time I would appreciate it if you could try and find a way to make the code position independent while losing little or no performance.

One thing to note is that I am now using an Opteron 1212 (2.0GHz dual-core) system for compiling, I run the i386 DomU with a 64bit kernel (I expect that 32bit user-space runs faster with a 64bit kernel than a 32bit kernel), and the disks are reasonably fast. Even so it takes about 15 minutes to build libswscale0 and the other packages from the same source tree. Previously I was using a 1.0GHz Pentium-3 for my Lenny i386 development until I had the libswscale0 build process go for more than 90 minutes before running out of disk space! If your build machine is old enough to only be 32bit then you should probably plan on watching a movie or going to bed while the build is in progress.

I have built packages that work around the above bugs and included them in my Lenny repository [4]. If you take the packages from that repository plus the Lenny packages then you should have a functional desktop system at level 1. I would appreciate it if people would start testing that and providing feedback. One important issue is the discovery of libraries that want shared stacks, text relocations, and executable memory. The deadline for fixing them properly is even more of a problem due to the number of people who have to be involved in a solution (as compared to the policy where I can do it on my own).

One finally problem is a bug in xdm which causes it to give the wrong context for login sessions due to having an old version of the SE Linux related code [5]. Due to a combination of this and some policy bugs you can not login with xdm. This is not a hugely important issue as most people will use gdm (which has the newer patch) or kdm (which has no SE Linux patch but can use pam_selinux.so). Also another option is wdm which works with pam_selinux.so. I’ve had a response to my bug report suggesting that there’s a bug in the patch (which was taken from gdm so maybe there’s a bug in gdm code too). I haven’t responded to that yet as I’ve been concentrating on the things that will make the most impact for Lenny.

At this stage I’m still unsure of when the release team will cut me off and prevent further SE Linux related fixes from going in Lenny. I need at least one more update to the policy packages before Lenny is released. I could release one right now with some useful improvements over what is currently in unstable, but am waiting until I get some other things fixed.

If I get everything fully working at level 1 (both client and server) before Lenny then I will provide a similar status report for users and testers of levels 2 and 3. I don’t expect that I will even get a chance to test level 4 (MLS) properly before Lenny releases.

Upgrading SE Linux Policy

When I first packaged the SE Linux policy for Debian the only way to adjust the policy was to edit the source files and recompile. Often changes that you might desire involved changing macros so while it would have been theoretically possible to just tack a few type definitions and allow rules at the end, you often wanted to change a macro to have a change apply all through the policy. To deal with that I had the policy source installed on all machines and the package update policy would compile it into a binary form and load it into the kernel.

Now there was the issue of merging user changes with changes from a new policy package. For most configuration files on a Unix system you can just leave any files that are modified by the user, not taking the new default configuration might cause the user to miss out on some new features – but presumably they were happy with the way it worked in the past. However due to inter-dependencies this wasn’t possible for SE Linux, if one file was not ungraded due to user changes and other files related to it were then the result could be a compile failure.

Another issue was the fact that a newer version of the policy might permit operations that the sys-admin did not desire and therefore not meet their security goals, or it might not permit operations that are essential to the operation of the system and interrupt service.

To solve this I wrote a script that prompted for upgrades to policy source files and allowed the sys-admin to choose which files to upgrade. This worked reasonably well in the early days when the number of files was small. But as the policy increased in size it became increasingly painful to upgrade the policy with as many as 100 questions being asked.

The solution to this (as implemented in Fedora Core 5, Debian/Etch, and newer distributions) was to have binary policy modules that maintain their dependencies. Now there are binary policy modules which can be loaded at will (the default install for Debian only installs modules that match the installed programs) and the modules can have optional sections with dependencies. So if you remove a module that defines a domain and there are other modules which have rules to allow communication with that domain then the optional sections of policy in the other modules is disabled when the domain becomes undefined. This solves the technical issues related to module inter-dependencies but the issue of intent and interaction with the rest of the system remains.

With Red Hat distributions the solution has been to upgrade the running policy every time the policy package is upgraded and be cautious when changing policy. They do a good job of the upgrade process (including relabeling files when the file contexts change) and in terms of policy changes I have not heard complaints from users about that. Users who don’t want a newer version of the policy can always put the package on hold.

For the Debian distribution after Lenny I plan to have a policy upgrade process that relabels files and a debconf question as to whether package upgrades should upgrade the policy. But for Lenny the freeze is already in progress so it seems to late to make such changes. Instead I’m going to upload a new version of the selinux-basics package with a program named selinux-policy-upgrade that will upgrade all the policy modules that are in use. This is not the ideal solution, but I think it will keep Lenny users reasonably happy.

2

Postfix and chroot

I have written a script named postfix-nochroot to disable the chroot functionality of Postfix. I plan to initially include this in the selinux-basics package in Debian, but if the script was adopted by the Postfix package or some other package that seems more appropriate then I would remove it from selinux-basics.

The reason for disabling chroot is that when running SE Linux the actions of the various Postfix processes are restricted greatly, such that granting chroot access would increase the privileges. Another issue is the creation of the chroot environment, the Postfix package in Debian will recreate the files needed for the chroot under /var/spool/postfix when it is started. The first problem with this is that when a package is ugraded the chroot environment won’t be upgraded (with the exceptions of some packages that have special code to restart Postfix) and when the sys-admin edits files under /etc those changes won’t be mirrored in the chroot environment either.

The real problem when running SE Linux is that it requires extra privileges to be granted to the Postfix processes (to be able to call chroot()). While the SE Linux policy places much greater restrictions on the actions of daemons than a chroot would. For example a non-chrooted daemon process running with SE Linux will not be able to see most processes in ps output (it will be able to see that processes exist through entries under /proc, but without the ability to search the subdirectories of /proc related to other processes it won’t be able to see what they are).

It would be possible for my script to be used as the first step towards making a Postfix installation automatically use a chroot when SE Linux is disabled or in permissive mode, and not use a chroot when SE Linux is in enforcing mode. I’ve probably done about half the work that is needed if this was the end goal, but I have no great interest in such configuration and no time to work on it. I would be prepared to accept patches from other people who want to go in this direction.

5

selinux-activate

I have written a script for Debian named selinux-activate which is included in selinux-basics version 0.3.3+nmu1 (which I have uploaded to Debian/Unstable). The script when run with no parameters will change the GRUB configuration to include selinux=1 on the kernel command-line and enable SE Linux support in the PAM modules for login, gdm, and kdm. One issue with this is that if you run the command before installing kdm or gdm then you won’t have the pam configuration changed – but as it’s OK to run the script multiple times this shouldn’t be a problem.

The new selinux-basics package will also force a reboot after relabelling all filesystems. I had tested “umount -a ; reboot -f” but discovered that “reboot -f” causes filesystem corruption in some situations (my EeePC running an encrypted LVM volume on an SD card had this problem). So I now use a regular “reboot“.

If no-one points out any serious flaws I plan to ask the release team to include this version of selinux-basics in Lenny. I believe that it will make it significantly easier to install SE Linux while also reducing the incidence of systems being damaged due to mistakes. If you edit the GRUB configuration file by hand then there is a risk of a typo making a system unbootable.

The package in question is already in my Lenny repository, see my previous post about Lenny SE Linux for details [1].

5

Installing SE Linux on Lenny

Currently Debian/Lenny contains all packages needed to run SE Linux apart from the policy. The policy package is missing because it needs to sit in unstable for a while before migrating to testing (Lenny), and I keep fixing bugs and uploading new versions.

I have set up my own APT repository for SE Linux packages (as I did for Etch [1]). The difference is that it’s working now (for i386 and AMD64) while I released my Etch repository some time after the release of Etch.

gpg --keyserver hkp://subkeys.pgp.net --recv-key F5C75256
gpg -a --export F5C75256 | apt-key add –

To enable the use of my repository you must first run the above two commands to retrieve and install my GPG key (take appropriate measures to verify that you have the correct key).

deb http://www.coker.com.au lenny selinux

Then add the above line to /etc/apt/sources.list and run “apt-get update” to download the list of packages.

Next run the command “apt-get install selinux-policy-default selinux-basics” to install all the necessary packages and then “touch /.autorelabel” to cause the filesystems to be labeled on the next boot. Edit the file /boot/grub/menu.lst and add “selinux=1” to the end of the line which starts with “# kopt=” and then run the command update-grub to apply this change.

Then reboot and the filesystems will be relabeled. Init will be running in the wrong context so you have to reboot again before everything is running correctly (I am thinking of having the autorelabel process automatically do the second reboot).

For future reference please use the page on my documents blog – I will update it regularly as needed [2]. This post will not be changed when it becomes outdated in a few days.

4

SE Linux in Lenny Status

SE Linux is almost ready to use in Lenny. Currently I am waiting on the packages libsepol1 version 2.0.30-2, policycoreutils 2.0.49-3, and selinux-policy-default version 0.0.20080702-4 to make their way to testing. The first two should get there soon, the policy will take a little longer as I just made a new upload today (to make it correctly depend on libsepol1 and also some policy fixes).

Update: libsepol1 version 2.0.30-2 and policycoreutils 2.0.49-3 are now in Lenny (testing). Now I’m just waiting for the policy.

Ideally we would be able to pin the apt repositories to take just the packages we want from Unstable (here is a document on how it’s supposed to work [1]). That doesn’t work, so I also tried setting “APT::Default-Release “stable”;” in /etc/apt/apt.conf (as suggested on IRC). This gave better results than pinning (which seems to not work at all) but it still wanted to take unreasonably large numbers of packages from unstable.

Currently to get SE Linux in Lenny (Testing) working you must first upgrade everything to the testing versions, then install libsepol1 from Unstable (this is really important as until a few hours ago the Policy packages in Unstable didn’t depend on it). Then you install policycoreutils and finally the policy package which will be selinux-policy-default for almost everyone – I have not tested the MLS package (selinux-policy-mls) and it’s quite likely that it won’t work well.

The policycoreutils package has a bug related to Python libraries [2] which I don’t know how to fix. Any advice would be appreciated. It’s obvious that the package name needs to not contain a hyphen, but what the name should be and where the files should be stored. The release team have been pretty cooperative with my requests so far to get broken things fixed, hopefully I’ll find a solution to this (and the other similar issues) soon enough to avoid any great inconvenience to them. I’m sure that they will agree that significantly broken packages (which have syntax errors in scripts) need to be fixed before release.

There are also some last minute policy issues that need to be fixed. To properly test this I’m now running the server for my blog and mail server on Lenny with SE Linux. I think that I’m only one policy bug away from running in enforcing mode.

While the situation is pretty difficult at the moment (I’ve had a report forwarded to me from an OLS delegate who tried Lenny SE Linux with the older policy packages and got a bad result), I believe that once Lenny is released we will have the best ever support for SE Linux.

The Debian security team recently released an update to the SE Linux policy packages to match the recent updates to BIND [3]. I was grateful that they did this – and without any significant involvement from me. I was asked to advise on the patch that they had written, I confirmed that it looked good (which took hardly any effort), and they did the rest (which appears to be a moderate amount of work). Given the situation it would have been understandable if they had decided that it was something that could be worked around.

I expect that SE Linux on Lenny will get more users than on Etch, so therefore more issues of this nature will be discovered so I expect to have more interaction with the Debian security group in future.

SE Linux Policy Loading

One of the most significant tasks performed by a SE Linux system is loading the “policy“. The policy is the set of rules which determine what actions are permitted by each domain.

When I first started using SE Linux (in 2001) the kernel knew where to find the policy file and would just read the data from disk as soon as it had mounted the root filesystem. Doing such things is generally considered to be a bad idea, but it was an acceptable mechanism for an early release.

One issue is that the policy needs to be loaded very early in the system boot process, before anything significant happens. In the early days the design of SE Linux had no support for a process to change it’s security context other than by executing another process (similar to the way a non-root process in the Unix access control system can not change it’s UID, GID, or groups). Although later on support for this was added, it was only available as the request of the application (an external process could not change the context of an application without using ptrace – a concept that is too horrible to contemplate) and I am not aware of anyone actually using it. So it’s almost a requirement that there be no more than one active process in the system at the time that policy is loaded, therefore it must be init or something before init that loads the policy.

When it was decided that a user-space program had to instruct the kernel to load the policy we had to determine which program should do it and when it should be done, with the constraint that it had to be done early. The most obvious solution to this problem was to load the policy in the initramfs (or initrd as it was known at the time). One problem with this is that the initramfs is limited in size by kernel compilation options and may need to be recompiled to fit a bigger policy. As an experiment to work around this limitation I had a small policy (which covered the domains for init and the scripts needed for the early stages for system boot) loaded in the initramfs and then later in the boot process (some time after the root filesystem was mounted read/write) the full policy was loaded.

A more serious problem with including policy in the initramfs was that it required rebuilding the initramfs every time the policy changed in a significant way, of course scripts could not determine when a change was significant (neither could most users) so that required needless rebuilds (which wastes time). Even with a small policy for early booting loaded it was still sometimes necessary to change it and update the initramfs. I believe that as a general rule an initramfs should only be rebuilt when a new kernel is installed or when a radical change is made to the boot process (EG moving from single disk to software RAID, changing between AMD and Intel CPU architecture, changing SCSI controller, or anything else that would make the old initramfs not boot the machine). The initramfs that was used to boot my machine is known to actually work, the same can not be said for any new initramfs that I might generate.

But the deciding factor for me was support of machines that did not use an initramfs or initrd (such as the Cobalt machines [1] I own).

To solve these problems I first experimented with a wrapper for init. The idea was to divert the real init to another file name (or use the init= kernel command-line option) and then have the wrapper load the policy before running the real init. I never intended that to be a real solution, just to demonstrate a point. Once I had proven that it was possible to load the policy from user-space before running the real init program it was a small step to patch init to do this.

One slightly tricky aspect of this was in getting the correct security context for init. The policy has always been written to allow a domain transition from kernel_t to init_t when a file of type init_exec_t is executed. The domain kernel_t is applied to all active processes (including kernel threads) at the time the policy is loaded. So init only has to re-exec itself to get the correct context. Fortunately init is designed to do this in the case of an upgrade so this was easy to manage.

Since that time every implementation of SE Linux apart from some embedded systems has used init to load the policy.

The latest trend in Linux distributions seems to be using upstart [2] as a replacement for the old SysV Init. The Fedora developers decided to make nash (a program that comes from the mkinitrd source tree in Fedora and is a utility program for a Red Hat based initramfs) load the SE Linux policy as it would apparently be painful to patch every init to load the policy.

As far as I am aware there are only three different init programs in common use in Linux, the old SysV Init (which used to be used by everyone), Busybox (for rescuing broken systems and for embedded systems), and now Upstart (used by Ubuntu and Red Hat since Fedora 9). Embedded systems need to work differently to other systems in many ways (having the one Busybox program supply the equivalent to most coreutils in one binary is actually a small difference compared to the other things), and modifying the policy load process for embedded systems is trivial compared to all the other SE Linux work needed to get an embedded system working well. There are at least two commonly used initramfs systems (the Debian and Red Hat ones) and probably others. As one init system (SysV Init) already has SE Linux support it seems that only one needs to be patched to have complete coverage. I’ve just written a patch for Upstart (based on the version in Debian/Experimental) and sent it to an Ubuntu developer who’s interested in such things. I also volunteer to patch any other init system that is included in Debian (I am aware of minit and will patch it as soon as it’s description does not include “this package is experimental and not easy to install and use“).

It seems to me that repeating the work which was done for SysV Init and upstart for any other init system will be little effort, at worst no greater than patching an initramfs systems (and I’ll do it). As the number of initramfs systems that would need to be patched would exceed the number of init systems it seems that less work is involved in patching the init systems.

The amount of RAM required by the initramfs is in some situations a limitation on the use of a system, when I recently did some tests on swap performance by reducing the amount of RAM available to a Xen DomU [3] it was the initramfs that limited how small I could go. So adding extra code to the initramfs is not desired. While this will be a small amount of code in some situations (when I patched /sbin/init from Upstart it took an extra 64 bytes of disk space on AMD64), dragging in the libraries can take a moderate amount of space (the fact that an LVM or encrypted root filesystem causes SE Linux libraries to be included in the initramfs is something that I consider to be a bug and plan to fix).

Finally not all boot loaders support an initrd or initramfs. I believe that any decision which prevents using such sweet hardware as Cobalt Qube and Raq machines from being used with SE Linux is a mistake. I have both Qube and Raq machines running fine with Debian SE Linux and plan to continue making sure that Debian will support SE Linux on such hardware (and anything with similar features and limitations).

5

New SE Linux Policy for Lenny

I have just uploaded new SE Linux policy packages for Debian/Unstable which will go into Lenny (provided that the FTP masters approve the new packages in time).

The big change is that there are no longer separate packages for strict and targeted policies. There is now a package named selinux-policy-default which has the features of both strict and targeted. When you install it you get the features of targeted. If you want the strict features then you need to run the following commands as root:

semanage login -m -s user_u __default__
semanage login -m -s root root

Then you can logout and login and you get the main benefit of the strict policy (users being constrained). IE you can convert from targeted to strict without a reboot! The above only changes the access for user login sessions (and cron jobs). To fully convert to the strict policy you need to remove the unconfined module with the command “semodule -r unconfined“, currently that results in a system that doesn’t boot – I’m working on this and will have it fixed before Lenny. Also it’s possible to have some users unconfined and some restricted in the way that strict policy always did.

When running in the full strict configuration you need to run the command “newrole -r sysadm_r” immediately after logging in as root. When you login you default to staff_r which doesn’t give you the access needed to perform routine sys-admin tasks.

Due to the change in the function of the policy packages (in terms of not having a strict package) it made sense to revise the naming (Fedora 9 has a package named selinux-policy-targeted which also provides the strict configuration – I don’t want to do that and don’t have as much legacy as Fedora). This is why I decided to not have package names that include the word “policy” twice. Of course all policy packages get new names, but the ones that matter needed new names anyway.

Another new feature is the package selinux-policy-mls, as the name suggests this implements Multi Level Security [1]. I don’t expect that the MLS policy will boot in enforcing mode in a regular configuration at this time (you could probably hack it to boot in permissive mode and switch to enforcing mode just before it starts networking). I uploaded it in this state so that people can start testing it (there is a lot of testing that you can do in permissive mode) and so that it can get added to the package list in time for Lenny. I expect that I’ll have it booting shortly (it should not be much more difficult than getting the strict configuration booting).

In terms of the use of MLS, I don’t expect that anyone will want to pay the money needed for LSPP [2] certification. NB The wikipedia page about LSPP really needs some work.

I believe that the main benefit for having MLS in Debian is for the use of students. I periodically get requests from students for advice on how to get a job related to military computer security. Probably the best advice I can offer is to visit the career section of an agency from your government that works on computer security issues, for US readers the NSA careers page is here [3]. The second best advice I can offer is to work on MLS support in your favourite free OS. Not only will you learn about technology that is used in military systems but you will also learn a lot about how your OS works as MLS breaks things. ;)

Finally I’d like to thank Manoj for all his work. For a while I didn’t have time to do much work on SE Linux and he did a lot of good work. Recently he seems to have been busy on other things and I’ve had a little more time so I’m taking over some of it.