Author: Corey Minyard, MontaVista Software

Chapter 1: First Touch on Customer Case

MontaVista received a customer request for creating an SELinux policy for a network appliance. The customer was working on adding a functionality for their customers to run applications on the appliance, and wanted as strict an isolation as possible between both the containers running on the appliance and the management system in all directions. These are security sensitive applications that need to be protected from the management system in case it is compromised, and from other containers, and the management system needs protection from the containers.

We had previously done a SELinux policy for another customer, so we reasoned that it wouldn’t be too hard. But we were wrong! Our previous case was for a larger system with disks and a more normal type of server configuration, while this system was a deeply embedded system with no disk, running from RAM completely. Its kernel booted with an embedded CPIO archive that the kernel unpacked for the root filesystem.

Diving into the work

SELinux is simple in concept, but crazy complicated to actually implement from scratch. Most of the complexity is often hidden by the standard policies that are available. First we started getting lxc to work on their system for containers, getting SELinux software enabled on the target, and the reference policy. The containers went quickly as we have significant experience with them. The SELinux software was somewhat harder. Many applications (busybox, lxc, PAM, etc.) and the kernel were SELinux enabled and needed some work to be able to build properly. PAM particularly was a pain: PAM has to be compiled, which would allow SELinux to compile. However, PAM is SELinux enabled and hence has to be re-compiled after SELinux is compiled to pick up the SELinux capabilities. We had experience with that sort of problem, so it wasn’t terrible.

The reference policy didn’t go so well. The first major issue we ran into was running on a ramdisk. We had to switch from the RAM block device in customer’s use to tmpfs because the RAM block device doesn’t support extended attributes, and therefore does not support SELinux contexts being added to the files. But thankfully tmpfs does.

Once we got tmpfs running, we started working on the reference policy. And it was huge and way too big for a system like what the customer had. Also, since we were running on tmpfs, and cpio has no way to store extended attributes, the security contexts for all the files had to be restored every time. We were able to get the reference policy onto the system and installed, but restoring the file security context took 40 seconds. Not acceptable.

Unfortunately, writing a full policy from scratch would blow our schedules by a large margin. An SELinux security policy has so many things that have to be accounted for just to get the basic functionality working. Then we would be stuck with maintenance of this thing. We could open source the base part, which would be good. But maintaining a security policy is not really what we do and it would be a long pull. I don’t think anyone has ever attempted anything like this before. But…

Enter OpenWRT

Fortunately, we discovered that the OpenWRT group was working on an SELinux policy for their distribution. The basics were done and they were mostly working on application support. It was like a gift from heaven. It was much more like what we needed, much smaller with support for the types of things you could expect on an embedded system.

It wasn’t perfect, however. It was written in CIL, a new policy language that the SELinux maintainers expected to switch to for everything eventually. Most importantly, it was unfamiliar to us. The basic concepts could transfer, but it was quite different in usage. Plus knowing CIL (like knowing the old kernel policy language) is not enough. You have to know how the policy writers have implemented their system to be able to use and extend it. 

Lots of studying and learning. Documentation was slight on this so it was mostly reverse engineering. OpenWRT stored what most distros put in /var in /tmp, while what we were working with was a more normal distro. Also, OpenWRT runs on squashfs, so tmpfs was not completely working. But these were surmountable issues. The file contexts could be restored in about a second, and the other issues didn’t take much time to fix. Learning took time, of course, but it was not too bad.

A Design For Security

Now we will get into the excruciating detail. The customer already had thought their system through and had a good basic security design. But even so, working on the security policy together uncovered issues in their software that could have been security issues. Instead of handling those with policy, we fixed them in the programs themselves.

Working with SELinux will require you to think about compartmentalization of your system to best provide security for critical data and best protect the system if an intrusion occurs. This is critical: A poorly designed system will not get much benefit from SELinux, but a poorly designed system is the most vulnerable.

Stay tuned for our next blog chapter!


Learn more about MVSecure services and MVXpert services.