SE Linux Status in Debian 2012-01

Since my last SE Linux in Debian status report [1] there have been some significant changes.

Policy

Last year I reported that the policy wasn’t very usable, on the 18th of January I uploaded version 2:2.20110726-2 of the policy packages that fixes many bugs. The policy should now be usable by most people for desktop operations and as a server. Part of the delay was that I wanted to include support for systemd, but as my work on systemd proceeded slowly and others didn’t contribute policy I could use I gave up and just released it. Systemd is still a priority for me and I plan to use it on all my systems when Wheezy is released.

Kernel

Some time between Debian kernel 3.0.0-2 and 3.1.0-1 support for an upstream change to the security module configuration was incorporated. Instead of using selinux=1 on the kernel command line to enable SE Linux support the kernel option is security=selinux. This change allows people to boot with security=tomoyo or security=apparmor if they wish. No support for Smack though.

As the kernel silently ignores command line parameters that it doesn’t understand so there is no harm in having both selinux=1 and security=selinux on both older and newer kernels. So version 0.5.0 of selinux-basics now adds both kernel command-line options to GRUB configuration when selinux-activate is run. Also when the package is upgraded it will search for selinux=1 in the GRUB configuration and if it’s there it will add security=selinux. This will give users the functionality that they expect, systems which have SE Linux activated will keep running SE Linux after a kernel upgrade or downgrade! Prior to updating selinux-basics systems running Debian/Unstable won’t work with SE Linux.

As an aside the postinst file for selinux-basics was last changed in 2006 (thanks Erich Schubert). This package is part of the new design of SE Linux in Debian and some bits of it haven’t needed to be changed for 6 years! SE Linux isn’t a new thing, it’s been in production for a long time.

Audit

While the audit daemon isn’t strictly a part of SE Linux (each can be used without the other) it seems that most of the time they are used together (in Debian at least). I have prepared a NMU of the new upstream version of audit and uploaded it to delayed/7. I want to get everything related to SE Linux up to date or at least with comparable versions to Fedora. Also I sent some of the Debian patches for the auditd upstream which should reduce the maintenance effort in future.

Libraries

There have been some NMUs of libraries that are part of SE Linux. Due to a combination of having confidence in the people doing the NMUs and not having much spare time I have let them go through without review. I’m sure that I will notice soon enough if they don’t work, my test systems exercise enough SE Linux functionality that it would be difficult to break things without me noticing.

Play Machine

I am now preparing a new SE Linux “Play Machine” running Debian/Unstable. I wore my Play Machine shirt at LCA so I’ve got to get one going again soon. This is a good exercise of the strict features of SE Linux policy, I’ve found some bugs which need to be fixed. Running Play Machines really helps improve the overall quality of SE Linux.

My Blog Server was Cracked

On the 1st of August I noticed that the server which runs my blog among other things was having an occasional SEGV from a sshd process. Unfortunately I was busy and didn’t pay much attention to this, which turned out to be a big mistake.

On the 12th of September I started investigating this properly and noticed that when someone tried to connect to ssh with password authentication sshd would SEGV after it was denied access to a shared memory region or a semaphore which had a SE Linux type of unconfined_t. I added some SE Linux auditallow rules and discovered that the memory region in question was created by the ssh client. Shortly after that I came to the conclusion that this wasn’t some strange feature of ssh (or one of the many shared objects it uses) but hostile activity. The ssh client appeared to be storing passwords that it used in a shared memory region and sshd was also collecting passwords in the same region and presumably offering them to a ssh client which uses some extension to the ssh protocol.

The sshd process was crashing because it couldn’t handle EPERM on access to shared memory or semaphores. Presumably if the system in question wasn’t running SE Linux then the exploit would have remained undetected for a lot longer.

At this stage we don’t know how the attacker got in. Presumably one of the people with root access ran a ssh client on a compromised system and had their password sniffed. One such client system was mysteriously reinstalled at about that time, the sysadmin of the system in question claimed to have no backups which made it impossible to determine if that system had been compromised. I believe that the sysadmin of the client system knew that their system was compromised, kept that information secret, and allowed other systems to become and remain compromised.

The attacker made no good effort to conceal their presence, they replaced ssh, sshd, and ssh-add and didn’t bother changing the Debian checksums so the debsums program flagged the files as modified. Note that I have kept copies of the files in question and am willing to share them with anyone who wants to analyse them.

Steinar H. Gunderson has named this trojan Ebury [1].

Recovery

By the evening of the 13th of September I had the system mostly working again. Jabber still isn’t working because ejabberd is difficult to get working at the best of times, I am now investigating whether there is a better Jabber server to use, but as I don’t use Jabber often this hasn’t been a priority for me.

Some of the WordPress plugins I use and all of the WordPress themes that are installed were outside the Debian packaging system, as I couldn’t be sure that they hadn’t been altered (because the people who wrote WordPress plugins don’t keep old versions online) I had to upgrade to the newer versions. Of course the newer versions weren’t entirely compatible so I had to use a different theme and I couldn’t get all plugins working. Link Within no longer works, not that it ever worked properly [2], I wanted to try Outbrain again but their web site won’t let me login (and they haven’t responded to my support request). Does anyone know of a good WordPress plugin to provide links to related content? Either related content on my blog or on the Internet in general will be OK.

Some people have asked me about the change in appearance of my blog. It was simply impossible (for someone with my PHP skills) to get my blog looking the same way as it did before the server was cracked. I think that the new look is OK and don’t mind if people think it looks likw a VW advert – VW make great cars, I was very satisfied with the VW Passat I used to drive.

Future Plans

I had bought some Yubikeys (USB devices that generate one-time passwords) [3] to control access to that server, if I had configured the software to use them then this might not have happened. The use of one-time password devices can prevent passive password-sniffing attacks. It would still allow active attacks (such as using ControlPath/ControlMaster options on the ssh client to allow a hostile party to connect later (EG the -M, -S, and “-o ControlPersist” options for the ssh client). It’s a pity that there doesn’t seem to be a way to configure the ssh server to disable ControlMaster.

Conclusion

It would be good to have some changes to sshd to allow more restrictions on what a client can request, as ControlMaster functionality isn’t needed by most users it should be possible to disable it.

SE Linux doesn’t protect against a compromised client system or any other way of stealing passwords. It did do a good job of stopping Ebury from doing all the things it wanted to do and thus making me aware of the problem. So I count this as a win for SE Linux.

Yubikeys are the cheapest and easiest way of managine one-time passwords. I had already bought some for use on the system in question but hadn’t got around to configuring them. I have to make that a priority.

Update 2014-04-09

MARC-ETIENNE M.LÉVEILLÉ wrote a good analysis of the Ebury trojan which is very similar (maybe the same) as this [4].

Secure Boot and Protecting Against Root

There has been a lot of discussion recently about the recent Microsoft ideas regarding secure boot, in case you have missed it Michael Casadevall has written a good summary of the issue [1].

Recently I’ve seen a couple of people advocate the concept of secure boot with the stated idea that “root” should be unable to damage the system, as Microsoft Software is something that doesn’t matter to me I’ll restrict my comments to how this might work on Linux.

Restricting the “root” account is something that is technically possible, for much of the past 9 years I have been running SE Linux “Play Machines” which have UID 0 (root) restricted by SE Linux such that they can’t damage the system [2] – there are other ways of achieving similar goals. But having an account with UID 0 that can’t change anything on the system doesn’t really match what most people think of as “root”, I just do it as a way of demonstrating that SE Linux controls all access such that cracking a daemon which runs as root won’t result in immediately controlling the entire system.

As an aside my Play Machine is not online at the moment, I hope to have it running again soon.

Root Can’t Damage the System

One specific claim was that “root” should be unable to damage the system. While a secure boot system can theoretically result in a boot to single user mode without any compromise that doesn’t apply to fully operational systems. For a file owned by root to be replaced the system security has to be compromised in some way. The same compromise will usually work every time until the bug is fixed and the software is upgraded. So the process of cracking root that might be used to install hostile files can also be used at runtime to exploit running processes via ptrace and do other bad stuff.

Even if the attacker is forced to compromise the system at every boot this isn’t a great win for the case of servers with months of uptime or for the case of workstations that have confidential data that can be rapidly copied over the Internet. There are also many workstations that are live on the Internet for months nowadays.

Also the general claim doesn’t really make sense on it’s own. “root” usually means the account that is used for configuring the system. If a system can be configured then the account which is used to configure it will be able to do unwanted things. It is theoretically possible to run workstations without external root access (EG have them automatically update to the latest security fixes). Such a workstation configuration MIGHT be able to survive a compromise by having a reboot trigger an automatic update. But a workstation that is used in such a manner could be just re-imaged as it would probably be used in an environment where data-less operation makes sense.

An Android phone could be considered as an example of a Linux system for which the “root” user can’t damage the system if you consider “root” to mean “person accessing the GUI configuration system”. But then it wouldn’t be difficult to create a configuration program for a regular Linux system that allows the user to change some parts of the system configuration while making others unavailable. Besides there are many ways in which the Android configuration GUI permits the user to make the system mostly unusable (EG by disabling data access) or extremely expensive to operate (EG by forcing data roaming). So I don’t think that Android is a good example of “root” being prevented from doing damage.

Signing All Files

Another idea that I saw advocated was to have the “secure boot” concept extended to all files. So you have a boot loader that loads a signed kernel which then loads only signed executables and then every interpreter (Perl, Python, etc) will also check for signatures on files that they run. This would be tricky with interpreters that are designed to run from standard input (most notably /bin/sh but also many other interpreters).

Doing this would require changing many programs, I guess you would even have to change mount to check the signature on /etc/fstab etc. This would be an unreasonably large amount of work.

Another possibility would be to change the kernel such that it checks file signatures and has restrictions on system calls such as open() and the exec() family of calls. In concept it would be possible to extend SE Linux or any other access control system to include access checks on which files need to be signed (some types such as etc_t and bin_t would need to be signed but others such as var_t wouldn’t).

Of course this would mean that no sysadmin work could be performed locally as all file changes would have to come from the signing system. I can imagine all sorts of theoretically interesting but practically useless ways of implementing this such as having the signing system disconnected from the Internet with USB flash devices used for one-way file transfer – because you can’t have the signing system available to the same attacks as the host system.

The requirement to sign all files would reduce the use of such a system to a tiny fraction of the user-base. Which would then raise the question of why anyone would spend the effort on that task when there are so many other ways of improving security that involve less work and can be used by more people.

Encrypted Root Filesystem

One real benefit of a secure boot system is for systems using encrypted filesystems. It would be good to know that a hostile party hasn’t replaced the kernel and initrd when you are asked for the password to unlock the root filesystem. This would be good for the case where a laptop is left in a hotel room or other place where a hostile party could access it.

Another way of addressing the same problem is to boot from a USB device so that you can keep a small USB boot device with you when it’s inconvenient to carry a large laptop (which works for me). Of course it’s theoretically possible for the system BIOS to be replaced with something that trojans the boot process (EG runs the kernel in a virtual machine). But I expect that if someone who is capable of doing that gets access to my laptop then I’m going to lose anyway.

Conclusion

The secure boot concept does seem to have some useful potential when the aim is to reboot the system and have it automatically apply security fixes in the early stages of the boot process. This could be used for Netbooks and phones. Of course such a process would have to reset some configuration settings to safe defaults, this means replacing files in /etc and some configuration files in the user’s home directory. So such a reboot and upgrade procedure would either leave the possibility that files in /etc were still compromised or it would remove some configuration work and thus give the user an incentive to avoid applying the patch.

Any system that tries to extend signature checks all the way would either be vulnerable to valid but hostile changes to system configuration (such as authenticating to a server run by a hostile party) or have extreme ease of use issues due to signing everything.

Also a secure boot will only protect a vulnerable system between the time it is rebooted and the time it returns to full operation after the reboot. If the security flaw hasn’t been fixed (which could be due to a 0-day exploit or an exploit for which the patch hasn’t been applied) then the system could be cracked again.

I don’t think that a secure boot process offers real benefits to many users.

SE Linux Status in Debian 2011-10

Debian/Unstable Development

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

The above APT sources.list line has my repository for SE Linux packages that have been uploaded to Unstable and which will eventually go to testing and then the Wheezy release (if they aren’t obsoleted first). I have created that repository for people who want to track SE Linux development without waiting for an Unstable mirror to update.

In that repository I’ve included a new version of policycoreutils that now includes mcstrans and also has support for newer policy such that the latest selinux-policy-default package can be installed. The version that is currently in Testing supports upgrading policy on a running system but doesn’t support installing the policy on a system that previously didn’t run SE Linux.

I have also uploaded SE Linux Policy packages from upstream release 20110726 compared to the previous packages which were from upstream release 20100524. As the numbers imply there is 14 months of upstream policy development which changes many things. Many of the patches from my Squeeze policy packages are not yet incorporated in the policy I have uploaded to Unstable. I won’t guarantee that an Unstable system in Enforcing mode will do anything other than boot up and allow you to login via ssh. It’s definitely not ready for production but it’s also very suitable for development (10 years ago I did a lot of development on SE Linux systems that often denied login access, it wasn’t fun).

Kyle Moffett submitted a patch for libselinux which dramatically changed the build process. As Manoj (who wrote the previous build scripts) was not contactable I accepted Kyle’s patch as provided. Thanks for the patch Kyle, and thanks for all your work over the years Manoj. Anyway the result of these changes should mean that it’s easier to bootstrap Debian on a new architecture and easier to support multi-arch – but I haven’t tested either of these.

Squeeze

The policy packages from Squeeze can’t be compiled on Unstable. The newer policy compilation tool chain is more strict about how some things can be declared and used, thus some policy which was fairly dubious but usable is now invalid. While it wouldn’t be difficult to fix those problems I don’t plan to do so. There is no good reason for compiling Squeeze policy on Unstable now that I’ve uploaded a new upstream release.

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

I am still developing Squeeze policy and releasing it in the above APT repository. I will also get another policy release in a Squeeze update if possible to smooth the transition to Wheezy – the goal is that Squeeze policy will be usable on Wheezy even if it can’t be compiled. Also note that the compilation failures only affect the Debian package, it should still be possible to make modules for local use on a Wheezy system with Squeeze policy.

MLS

On Wednesday I’m giving a lecture at my local LUG about MLS on SE Linux. I hope to have a MLS demonstration system available to LUG members by then. Ideally I will have a MLS system running on a virtual server somewhere that’s accessible as well as a Xen/KVM image on a USB stick that can be copied by anyone at the meeting.

I don’t expect to spend much time on any aspect of SE Linux unrelated to MLS for the rest of the week.

Version Control

I need to change the way that I develop SE Linux packages, particularly the refpolicy source package (source of selinux-policy-default among others). A 20,000 line single patch is difficult to work with! I will have to switch to using quilt, once I get it working well it should save me time on my own development as well as making it easier to send patches upstream. Also I need to setup a public version control system so I can access the source from my workstation, laptop, and netbook. While doing that I might as well make it public so any interested people can help out. Suggestions on what type of VCS to use are welcome.

How You Can Help

Sorting out the mess that is the refpolicy package, sending patches upstream and migrating to a VCS is a fair bit of work. But there are lots of small parts. Sending patches upstream is a job that could be done in small pieces.

Writing new policy is not something to do yet. There’s not much point in doing that while I still haven’t merged all the patches from Squeeze – maybe next week. However I can provide the missing patches to anyone who wants to review them and assist with the merging.

I have a virtual server that has some spare capacity. One thing I would like to do is to have some virtual machines running Unstable with various configurations of server software. Then we could track Unstable on those images and use automated testing to ensure that nothing breaks. If anyone wants root access on a virtual server to install their favorite software then let me know. But such software needs to be maintained and tested!

Capabilities vs SE Linux

In December 2010 a paper was published by Robert N.M. Watson and Jonathan Anderson from the Cambridge University and Ben Laurie and Kris Kennaway of Google about the Capsicum capabilities system [1]. It seems that the aim of the project is to allow systems that need privileges briefly when they start (such as tcpdump) a safe method of dropping privs. The main project page is here [2].

The focus of the paper is on the Chromium web browser and six different ways of constraining the Chromium sandbox are compared. For the SE Linux comparison they claim 200 lines of code changes as of Fedora 15, in Fedora 16 I couldn’t find a Chromium package, so I presume that they mean 200 lines of SE Linux policy (I am not aware of anyone modifying the Chromium source for SE Linux). They note that SE Linux doesn’t support separating different sandboxes, while it would be possible to have each sandbox be assigned a different MCS sensitivity label to separate them that option would be unwieldy enough that they are essentially correct in this regard. For SE Linux systems running the MLS policy the correct thing to do would be to run multiple copies of Chromium at different levels to access different sensitivity levels of data, this would normally be done by polyinstantiating the home directory.

One thing to note however is that there is no requirement that only one security method be implemented. I can’t think of any technical reason why it would be impossible to run SE Linux and Capsicum on the same system. SE Linux could constrain daemons and restrict the access to Capsicum services while Capsicum could be used to give minimum privileges to parts of Chromium. I’m not sure that such a combination would offer anything that the MLS users would desire, but it seems that everyone else (the vast majority of computer users) would be served well by a combination of SE Linux and Capsicum.

It’s disappointing that the paper didn’t mention Posix 1003.1e capabilities, but given the lack of use that Posix capabilities get that’s understandable.

It’s also disappointing when someone develops something new and different nowadays and doesn’t provide a virtual machine image for it. Installing and configuring something that requires application and kernel changes is a lot of work and most people who are idly curious about the technology won’t go to the effort. By today’s standards it’s not that difficult to share a 1GB filesystem image via Bittorrent.

SE Linux File Context Precedence

In my previous post I expressed a desire to use regular expressions for files that may appear in multiple places in the tree due to bind mounts for /run and /var/run etc [1]. However there is a problem with this idea.

The SE Linux file labeling program restorecon reads the file /etc/selinux/$SELINUXTYPE/contexts/files/file_contexts which contains a set of regular expressions to assign labels to files. That file is ordered and the last entry which matches is the one that counts. When the file_contexts file is created the order is based on how many characters at the start of the file specification aren’t regular expression meta-characters. For example the entry “/.*” is at the top of the file (and therefore has the lowest precedence), which makes it the catch-all entry for files that have no other match. So an entry for “/var/run/REGEX” will have a higher precedence than one for “/var/REGEX”, this means however that when I replaced the “/var/run” part with a regular expression then it had a lower precedence and it didn’t work properly.

I should have remembered this as I did a lot of work on setfiles (which became restorecon) in the early days. I have now developed a new way of solving this and this time I’m testing it before blogging about it.

I have written the following PERL program to fix the file contexts, this adds multiple lines and uses a distro_debian conditional on them so that they don’t slip into upstream use – and so that if I lose track of where each patch came from I’ll know that I can delete them in future because it only matters to Debian.

#!/usr/bin/perl
use warnings;
use strict;

open(LIST, "find . -name \"*.fc\"|xargs egrep \"^/(var.*run)|(var/lock)|(dev/shm)\"|cut -f1 -d:|uniq|") or die "Can't get file list\n";
while(<LIST>)
{
  my $filename = $_;
  chomp $filename;
  open(my $infile, "<", $filename) or die "Can't open file $filename";
  open(my $outfile, ">", $filename . ".new") or die "Can't open file ". $filename . ".new";
  while(<$infile>)
  {
    print $outfile $_;
    my $newline;
    if($_ =~ /^\/var\/run/)
    {
      print $outfile "ifdef(`distro_debian', `\n";
      $newline = $_;
      $newline =~ s/^\/var//;
      print $outfile $newline;
      print $outfile "')\n";
    }
    if($_ =~ /^\/var\/lock/)
    {
      print $outfile "ifdef(`distro_debian', `\n";
      $newline = $_;
      $newline =~ s/^\/var/\/var\/run/;
      print $outfile $newline;
      $newline =~ s/^\/var//;
      print $outfile $newline;
      print $outfile "')\n";
    }
    if($_ =~ /^\/dev\/shm/)
    {
      print $outfile "ifdef(`distro_debian', `\n";
      $newline = $_;
      $newline =~ s/^\/dev/\/run/;
      print $outfile $newline;
      print $outfile "/var" . $newline;
      print $outfile "')\n";
    }
  }
  close($infile);
  close($outfile);
  rename $filename . ".new", $filename or die "Can't rename " . $filename . ".new to " . $filename;
}

The next policy thing that I have to work on is systemd. From a quick test it seems that systemd policy changes will be more invasive than is suitable for Squeeze. This means that someone who wants to upgrade from Squeeze to Wheezy+systemd will have to upgrade to Wheeze policy before installing systemd. I think that I will make 0.2.20100524-10 the last version in Unstable based on the 2010 release, I will now start work on packaging the latest upstream policy for Unstable.

PS I’m not much of a PERL programmer, so if anyone has suggestions for how to improve the above PERL code then please let me know. Please note however that I’m not interested in making my code look like line-noise.

/run and SE Linux Policy

Currently Debian/Unstable is going through a transition to using /run instead of /var/run. Naturally any significant change to the filesystem layout requires matching changes to SE Linux policy. We currently have Debian bug #626720 open about this. Currently the initscripts package breaks selinux-policy-default in Debian/Unstable so that you can’t have initscripts using /run if the SE Linux policy doesn’t support it.

A patch has been suggested to the policy which uses a subst file, basically that causes the SE Linux labeling programs to treat one directory tree the same way as another. The problem with this is that it depends on a libselinux patch that is not in any yet released version of libselinux (and certainly won’t be in a Squeeze update). The upside of such a fix is that it would work for policy that I package as well as custom policy, so if someone wrote custom policy referring to /var/run it would automatically work with /run without any extra effort.

I think that the only way to do this is to just have regular expressions that deal with this in the file contexts. It’s a bit ugly and slows the relabel process down a little (probably no more than about 10%) but it will work – and work on Squeeze as well. One thing I really like to do is to have the SE Linux policy for version X of Debian work with version X+1. This makes upgrades a lot easier for the users. Ideally upgrading a server could be a process that involves separate upgrades of the kernel, the SE Linux policy, and user-space in any particular order – because upgrading everything at once almost guarantees that something will break and it may be difficult to determine the cause.

At this time I’m not sure whether I’ll add a new policy using the subs file before the release of Wheezy (the next stable release of Debian) or just keep using regular expressions. I can have the Wheezy policy depend on a new enough libselinux so it won’t be a problem in that regard (a new upstream version of libselinux with the subst feature should be released soon). In any case I need a back-port to Squeeze to use regular expressions to make an upgrade to Wheezy easier.

for n in $(find . -name "*.fc"|xargs grep var/run|cut -f1 -d:|uniq) ; do
  sed -e "s/\/var\/run/\/(var\/)?run/" < $n > $n.new
  mv $n.new $n
done
for n in $(find . -name "*.fc"|xargs grep var/lock|cut -f1 -d:|uniq) ; do
  sed -e "s/\/var\/lock/\/((var\/run)|(run)|(var))\/lock/" < $n > $n.new
  mv $n.new $n
done
for n in $(find . -name "*.fc"|xargs grep dev/shm|cut -f1 -d:|uniq) ; do
  sed -e "s/\/dev\/shm/\/((var\/run)|(run)|(dev))\/shm/" < $n > $n.new
  mv $n.new $n
done

I used the above fragment of shell code to change “/var/run” to “/(var/)?run”, “/var/lock” to “/((var/run)|(run)|(var))/lock”, and change “/dev/shm” to “/(var/run)|(run)|(dev))/shm”. It involves a reasonable number of changes to policy (mostly for /var/run), but hopefully this will be acceptable to the release team for inclusion in the next Squeeze update as the changes are relatively simple and obvious and the size of the patch is due to it being generated code.

There is one final complication, Squeeze currently has selinux-policy-default version 2:0.2.20100524-7+squeeze1, but initscripts in Unstable breaks versions <= 2:0.2.20100524-9. So I guess I could submit a proposed version 2:0.2.20100524-9+squeeze1 to the release team to fix this. I would really like to have the Squeeze policy work with initscripts from Unstable or Wheezy.

Any suggestions for how to deal with this?

Update:

I wrote the above before testing the code, and it turned out to not work. I’ve written another post describing a better solution that I have now uploaded to Unstable. I still have to sort something out with an update for Squeeze.

Multiple Filesystems for Security

There is always been an ongoing debate about how to assign disk space into multiple partitions. I think that nowadays the best thing to do is to assign about 10G for the root filesystem for every desktop and server system because 10G is a small fraction of the disk space available (even the smallest laptops seem to all have disks larger than 100G nowadays). Even if 10G turns out not to be enough using separate filesystems for /var or /usr provides little benefit now that it’s easy to resize the root filesystem with LVM – and a separate /usr is known to be broken [1].

In a discussion on a private mailing list there was a suggestion that multiple filesystems should be used for security.

DoS Attacks

There are some minor security benefits in having multiple filesystems. If a critical program will fail when there is no free disk space then allowing an unprivileged process to use up all the space on that filesystem is a minor security issue, so having unprivileged processes not being permitted to write to important filesystems is a benefit. But most failures of this type are merely DoS attacks which usually aren’t a big deal – if you can control a local process there are usually lots of other ways of DoSing a system.

Links

Links have been the cause of many security issues in Unix over the years. Using different filesystems for different tasks can prevent the use of hard links in attacks aimed at exploiting race conditions. But even if you prevent hard links there are similar issues with symbolic links. SE Linux is one of many security improvements for Linux which allow restrictions on the creation of hard links. SE Linux also allows restricting the ability of processes to follow symbolic links, so a privileged process can be denied access to follow a sym-link that was created by an unprivileged process.

NFS

The subtree_check option in /etc/exports causes the NFS server to verify that file access is in the correct subtree. So if you export only one subdirectory of a filesystem to a given server then hostile code on that server (or on a network device which impersonates that server) can’t access other subdirectories. This option is documented as having performance implications and working best for filesystems that are mostly read-only, for this reason it’s turned off by default in recent versions of the NFS utilities.

So if you want to NFS export /home then it’s probably a good idea to have /home be on a separate filesystem to prevent attacks on the root filesystem. But of the systems with significant use of /home (IE anything other than accounts used solely for “su –“) most of them have a separate filesystem for /home anyway so this shouldn’t be an issue.

SE Linux

When mounting filesystems with SE Linux there is a “context=” mount option that allows specifying the context for all files on the filesystem. This can save a small amount of storage space for XATTRs and theoretically improve performance (although the difference is unlikely to show up on benchmarks for anything other than fsck). Generally the context mount option is only used for a filesystem that has a huge number of files with the same context, such as a mail spool that uses Maildir, Cyrus, or any of the other formats that involve one file per message. But again such data is generally stored on a separate filesystem for other reasons anyway.

I found one interesting corner case in regard to SE Linux systems mounting files from an NFS server. When an NFS server exports multiple subdirectories of a filesystem mounted on /foo then if one NFS client running SE Linux is to mount two subdirectories of /foo with different contexts then the second mount attempt will give the error “an incorrect mount option was specified”. This is because as of kernel 2.6.18 by default it’s not permitted to mount parts of the same filesystem with different mount options. The option “nosharecache” allows you to use different mount options, but does apparently permit some undesirable behavior in the case of hard links that cross between the subtrees. Thanks to Eric Paris for the tip about nosharecache.

The best example I can think of for which you might want context mount options that differ among files that are used for the same purpose on an NFS mount is a web server which has data files and CGI-BIN scripts. So it seems that a SE Linux web server that mounts it’s data over NFS and is at risk of having hard links between the CGI-BIN directory and the data directory is a corner case in which multiple filesystems is required for security. This seems to be a very unlikely case.

Conclusion

Servers that are deployed in the real world are complex enough that there are always systems with some unusual corner cases demanding configuration choices that aren’t expected. There are some real corner cases for SE Linux where multiple filesystems are compelled for security or for a combination of security and best performance.

But I wouldn’t make a generic recommendation of using lots of filesystems for security. I think that the people who encounter the strange corner cases can usually work out that they need to do something different. So a small number of filesystems seems like a good general aim that doesn’t conflict with security.

What is Valid SE Linux Policy?

Guido Trentalancia started an interesting discussion on the SE Linux policy development list about how to manage the evolution of the policy [1].

The Problem

The SE Linux policy is the set of rules that determine what access is granted. It assigns types to files and domains to processes and has a set of rules that specify all the permitted interactions between processes and files (among many other things). The policy evolves over time to match the requirements of programs (applications and daemons). As a program evolves the things that it does will change and the SE Linux policy will tend to evolve to permit the set of all operations that were requested by all versions because people only complain when things stop working not when excessive privilege is granted. So we need to periodically remove old allow rules from the policy.

One difficulty in this regard is the fact that multiple versions of programs are often available for use at the same time. Debian in particular has a good history of providing separate packages for the old and new versions of programs such as Apache to meet the needs of users who want the tried and tested version and of users who want the newer version with better performance, more features, better documentation, or something else good. There is also a demand to have the same policy work with multiple versions of a distribution without excessive effort. Finally all the distributions that have SE Linux support have different people deciding when the new version of a daemon is ready for inclusion and therefore there is a need to support multiple versions for multiple distributions. So support for older versions of daemons can’t be removed easily.

One of the things I do to make these things a little easier to manage is to put ifdef(`distro_debian', ` before any Debian specific bits of policy. When policy is conditional and only used in Debian I can freely remove it at any future time if Debian works well without it. Also it doesn’t matter if such Debian specific policy allows access that is not needed or desired in other distributions, the only down-side to this is that sometimes other distributions need to repeat work that I did, they determine what access is needed for their configuration and discover that it was already enabled for Debian.

What is Valid Policy?

We went to only have “Valid Policy” (as described by Christopher J. PeBenito), so the challenge is determining what is Valid Policy.

It seems to me that there are three type of access granted by valid policy (it is debatable whether type #3 is valid):

  1. Access that is needed for an application to perform it’s minimal designed task.
  2. Access that is needed for the application to perform all the optional configurations, EG an ftpd running from inetd or as a daemon, and daemons like http server being granted access to ssl keys or not.
  3. Access that is needed to perform all the operations the application requests, but which the application doesn’t require or shouldn’t require if it worked correctly.

Some common operations that aren’t required include opening utmp for write, searching /root, and many other relatively innocuous access attempts which don’t affect the program operation if they are denied. There are also many things such as writing temporary files to /root that don’t seem unusual if the application developer is not considering SE Linux (but which are often considered bad practice anyway). Some of these things (like using /root for stuff that belongs in /var/lib) have the potential to break things (for the daemon or for other system processes) even if you don’t consider SE Linux.

How to deal with those types:

  1. In most cases this can be determined without too much effort. For example a web server needs to listen on port 80 and read files and directories that relate to data. When writing policy I can write a lot of the allow rules without even testing the application because I know from the design what it will do. A large part of the other access is obvious in a “I can’t believe I didn’t realise it would need this” sense.
  2. The main question here is whether we have booleans (settings which can be tuned at run-time by the sysadmin which determine how the policy works) to specify which optional tasks or whether we allow all access for optional configurations by default. The secondary question is when certain unusual corner cases should be not supported at all such that the people who do such unusual corner cases need to use audit2allow to generate local policy to allow their operations.
  3. Sometimes we have to allow things that we really don’t like. Even when we write policy to allow a daemon to do unusual things (such as using /root instead of /var/lib) it’s still a lot better than running without SE Linux. Also SE Linux policy to allow such obviously broken things stands out and is a constant reminder that the daemon needs fixing, this is better than allowing symptoms of broken design to be forgotten.

How to Improve the Situation

We could have comments in the policy source for everything that is in category 3. If the comments had a fixed format so that a recursive grep could find them all then it would allow us to more easily remove the gross things from the policy at a later date.

But it seems to me that the main problem is a lack of people working on this. I am not aware of any people actively testing Debian policy for excessive privilege in regard to such issues.

Mplayer, Squeeze, and SE Linux on i386

I’ve just updated my SE Linux repository for Squeeze to better support running mplayer on the i386 architecture, below is the APT sources.list line:

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

The first issue is a bug in the compilation of the SDL libraries which makes them request an executable stack (bug #613535). Recompiling the libraries on my system caused this bug to go away, so it must be some issue with the compilation process. I have previously summarised the execstack issue, but we haven’t solved this yet [1].

The next issue is the fact that the ffmpeg libraries require execmod access (see my previous post for the details of the execmod issue [2]. The execmod issue with ffmpeg is pretty much the same as it was when I first wrote about the issue in 2008 [3]

Finally the allow_execmem boolean needs to be set on i386 with the command “setsebool -P allow_execmem 1” to allow libGL the access it needs. This is an issue I haven’t been able to solve, I don’t know why libGL needs write and execute access to memory, I posted to the SE Linux list about this some time ago but didn’t get any good answers [4]. Any suggestions would be appreciated.