Last week we took the eagle’s eye view of the principles behind SELinux. Today we’ll dig a bit more deeply into SELinux policies, and then fire up Fedora 8 and see what SELinux looks like in practice. I recommend using the latest Fedora version as a SELinux training tool, because Fedora has the most mature implementation and userspace tools. Red Hat Enterprise Linux and CentOS, the leading Red Hat clone, have similar SELinux setups to Fedora. Gentoo also has a nice SELinux implementation. I don’t recommend starting from scratch. Start with a working setup, and then plan to spend considerable time learning your way around it, because it is a big complex beast.
It’s not that SELinux itself is so complex; it’s the scale of it. SELinux wants to touch every file and process on your system. Fedora, RHEL, and Gentoo come with prefab policies, and this is a good thing because writing SELinux policies is a large undertaking. To write a good policy you need a thorough understanding of what your application does, and how it interacts with everything else on a system. Dan Walsh, the lead SELinux developer for Red Hat, cheerily claims that “customizing your system’s protection by creating new policy modules is easier than ever!” Which is very much a relative statement, akin to “Thanks to modern high-tech gear, visiting the Moon is easier than ever!” But it’s not impossible, and Mr. Walsh is encouraging and helpful, having written reams of SELinux documentation.
For now we’re going to make sure we understand SELinux fundamentals, and take a look at the nice Fedora tools for managing SELinux.
Policies: The SELinux Master Control Center
SELinux uses policiesto enforce mandatory access controls (MAC), which you’ll recall from part 1 foil zero-day attacks and privilege escalation, so let’s see what goes into making a policy.
SELinux calls users, processes, and programs subjects. objectsare files, devices, sockets, ports, and sometimes other processes. Subjects can be thought of as processes, and objects are the targets of a process operation.
SELinux uses a kind of role-based access control (RBAC) combined with type enforcement. Type enforcement enforces policy rules based on the types of processes and objects, which it tracks in a giant table. Types and domainsare the same thing; you’ll see both terms a lot.
Type enforcement means every subject on the system—that’s right, all of them&mash;has to have a type assigned to it. Types are stored in security contexts in the extended attributes (xattrs) of the files. This means they are stored in the inodes, which means that no matter how many weirdo soft or hard links are attached to your file, the security context is inescapable, and will not be fooled by silly evasions such as renaming the files or creating crafty softlinks.
Types are included in the security context. A security context has three elements: identity, role, and typeidentifiers, like this:
You can see these with the Z option to the lscommand:
$ ls -alZ /bin/ping -rwsr-xr-x root root system_u:object_r:ping_exec_t:s0 /bin/ping
What do these things mean? system_u is a system user. Files on disk do not have roles, so they are always object_r. ping_exec_t is the type for the ping command. You will also see documentation that calls this the domain.
The security context is used by your SELinux policy to control who can do what. The identity controls which domains the process is allowed to enter. This is defined somewhere inside the vast directory — /etc/selinux— that contains your SELinux policy. In the targeted SELinux policy, every subject and object runs in the unconfined_t domain, which is just like running under our old familiar Unix DAC (Discretionary Access Control) permissions. Except for a select set of daemons that are restricted by SELinux policy and run in their own restricted domains. For example, httpd runs in the httpd_t domain, and is tightly restricted so that a successful intrusion will be confined to the HTTP process, and not gain access to the rest of the system. Nor will users or processes who have no business with httpdbe allowed to interfere with its operation, or access data files they have no business looking at.
The pscommand will show you some examples of this in action:
$ ps aZ
LABEL PID TTY STAT TIME COMMAND
system_u:system_r:getty_t:s0 2587 tty1 Ss+ 0:00 /sbin/mingetty tty1
system_u:system_r:xdm_xserver_t:s0:c0.c1023 2664 tty7 Ss+ 7:38 /usr/bin/X
What does the s0 mean? Well now, that opens a whole new can o’ terminology. That field belongs to Multilevel Security (MLS); it sets a sensitivity value that ranges from s0-s15. When you use MLS you also need a capabilitiesfield, which goes from c0 – c255, so it would look something like s1:c2. MLS is super-strict and overkill for most of us. So instead Fedora uses Multi-Category Security (MCS). The MLS sensitivity field is required by the kernel and it always says s0, but you can ignore it. MCS allows you to further refine access controls with user-defined categories.
For example, you could have a MCS category called “super-secret!_yes_really!”. Then files labeled with this will be accessible only to processes with permissions to enter this category. In the ps output above, you’ll see an example of this with the X process. If you want to try your hand at these read A Brief Introduction to Multi-Category Security (MCS), and Getting Started with Multi-Category Security (MCS).
While most files can be controlled by SELinux without any modifications, a few have had to be patched to become SELinux-aware, such as the Linux coreutils files, login programs like login, sshd, gdm, cron, and the X windows system. You should also find these on systems that do not ship with SELinux, such as Ubuntu. If your system does not have SELinux, they will return empty fields where the SELinux labels should go, like this psexample:
$ ps aZ
LABEL PID TTY STAT TIME COMMAND
- 4248 tty4 Ss+ 0:00 /sbin/getty 38400 tty4
- 4249 tty5 Ss+ 0:00 /sbin/getty 38400 tty5
The nice SELinux devs have kindly made Z the universal “show me the security context” option. SELinux comes with it own set of user-space commands, which are bundled up in the policycoretutilspackage. You can run a number of SELinux commands without hurting anything, like see your own personal security context:
$ id -Z system_u:system_r:unconfined:t:s0
You can check SELinux status:
SELinux status: enabled
SELinux mount: /selinux
Current mode: permissive
Mode from config file: permissive
Policy version: 21
Policy from config file: targeted
avcstat displays AVC (Access Vector Cache) statistics. avcstat 5runs it every five seconds; of course you can make this any interval you want.
Fedora’s SELinux Tools
Fedora 7 and 8 have three good graphical SELinux tools: SELinux Management, SELinux Policy Generation Tool, and SELinux Troubleshooter. Start with SELinux Management; this lets you fine-tune the existing SELinux policy, or change to a different policy type entirely.
It costs nothing but time and a spare PC to learn your way around this potent security tool. I’ve seen a lot of comments on forums and mailing lists that say it’s too complex to bother with. I don’t agree with this; I think a security tool of this nature is overdue for Linux. Any Internet-facing server is a good candidate for SELinux, and especially the notoriously porous category of LAMP servers.
What about AppArmor and GRSecurity? We’ll soon be looking at these as well.
- Dan Walsh’s LiveJournal contains reams of SELinux howtos, which is good because he is the lead Red Hat SELinux developer. Yes, it’s all his fault!
- A step-by-step guide to building a new SELinux policy module
- SELinux FAQs
- SELinux Commands
- Targeted Policy Overview