Kernel Korner

NSA Security Enhanced Linux

Faye Coker

Issue #112, August 2003

With fine-grained mandatory access controls in your system, you can even put limits on what root can do.

NSA Security Enhanced Linux has its roots in the distributed trusted operating system (DTOS) and Flask (Flux advanced security kernel) architecture. The DTOS Project was a collaborative effort between the US National Security Agency (NSA) and Secure Computing Corporation (SCC) in the early and mid-1990s. The goal was to provide stronger operating system security mechanisms than those provided by standard security methods. The Flask architecture was the result of a joint effort between the NSA, SCC and the University of Utah's Flux Project, which was “enhanced to provide better support for dynamic security policies” (www.cs.utah.edu/flux/flask, “Flask: Flux Advanced Security Kernel” by Stephen Smalley, NAI Labs, December 26, 2000).

SE Linux implements mandatory access control, or MAC, while regular UNIX systems employ discretionary access control, or DAC. With DAC, users can control what access is applied to objects they own at their discretion. On a UNIX system, for example, they can use the chmod command to change permissions on directories they own. With MAC, access control is decided by a more authoritative user who configures security policies that determine what access rights an object possesses. If a policy is preventing Bob from accessing Alice's home directory, and Alice runs chmod 777 on her home directory, Bob still would not be able to access it.

When utilizing MAC, processes are run with a minimum amount of privilege, and a compromised process cannot grant other processes inappropriate access to its own resources. This reduces the amount of damage that might occur if a dæmon was compromised. Security decisions are based on a number of factors, such as the role of the user, what type of program is being run, how trusted that program is and the secrecy level or integrity of the data being accessed.

What Is SE Linux?

SE Linux is an implementation of flexible, fine-grained mandatory access controls in the Linux kernel that is now implemented using the LSM framework (see “Using the Kernel Security Module Interface” by Greg Kroah-Hartman, LJ, November 2002). In its current implementation, the LSM interface supports only restrictive access controls. Therefore, if the standard UNIX permissions deny an operation, SE Linux cannot permit it. SE Linux generally is used to apply additional restrictions to a system that employs UNIX permissions, and it is quite capable of enforcing all necessary access controls on its own. However, it is strongly recommended that a combination of UNIX permissions and SE Linux be used for “defense in depth” on production servers. SE Linux is comprised of a kernel patch and patches to utility programs such as login and cron.

The NSA is responsible for official releases. A number of other people outside the NSA also contribute code to the project. Packages are maintained constantly for the Debian stable and unstable releases. As SE Linux is licensed under the GPL, anyone can contribute and make her own modifications. SE Linux can be used on 2.4.19 kernels and above, and at the time of this writing, May 2003, it is being redeveloped for the 2.5 kernel.

Why Are Modified Utilities Required?

As previously mentioned, SE Linux is comprised of a kernel patch and modified utility programs. The modified utilities ensure that all files on the system possess the correct security context. Modified versions of utilities, such as login, cron and logrotate, and programs, such as ps and ls, are available. With login, for example, it is crucial to have the correct security contexts when a user logs in to the system. If not, he might not be able to log in at all.

Installing the login package is covered in the Getting Started with SE Linux HOWTO (see Resources) and is beyond the scope of this article. Forgetting to install the login package during the SE Linux installation, however, results in not having the right type assigned to the terminal device from which you are logging in after a reboot, which renders you unable to log in. An unmodified login program also runs a shell in a security context that is denied access to files in the user's home directory. The patches for login and cron, for example, tell the kernel which security context to use. The actual enforcement of these measures is done by the kernel. Labeling is imperative, hence the need for some modified programs. It is possible to create your own security policies that provide basic levels of protection without having to to install modified packages, but the default configuration provides finer-grained security.

Frequently Used Terms

When reading documents on SE Linux or mailing list posts, the following terms always are used. It is important to familiarize yourself with them as much as possible before you attempt to install SE Linux. Doing so makes things much easier later on.

Domain: a domain details what processes can and cannot do or, rather, what actions a process can perform on various types. If you are in the user_t domain (the standard unprivileged user domain) and you run the command ps aux, you see only the processes running in the user_t domain. Some examples of domains are sysadm_t, the system administration domain, and init_t, the domain in which init runs. The domain in which the passwd program is run by an unprivileged user is passwd_t.

Role: a role determines what domains can be used. The domains that a user role can access are predefined in the policy database. If a role is not authorized to enter a domain (in the config files), it is denied. Some examples of roles are the general unprivileged user role (user_r) and the system administrator role (sysadm_r).

Consider the following example: in order for a user from the user_t domain to execute the passwd command, role user_r types passwd_t ; is specified in the relevant config file. In addition, other domain transitioning rules must be set that are not covered here. This added code states that a user in the user role (user_r) is allowed to enter the passwd_t domain, so he can run the passwd command. Another consideration is whether the old domain is allowed to transition to the new domain.

Now that we have defined domains and roles, we can look at comparisons between SE Linux and the standard UNIX uid (user ID). If root owns a program with UNIX permissions 4777 (making the program setuid root), any user on the system can execute that program, resulting in a security issue. With SE Linux, however, if a process triggers a domain transition to a privileged domain and the role of the process is not authorized to enter a particular domain, the program cannot be run. Every process on an SE Linux system runs in a domain that determines what access rights a process possesses.

Identity: an identity under SE Linux is not the same as the traditional UNIX uid with which most readers might be familiar. Identities under SE Linux form part of a security context that controls what you can and cannot do. An SE Linux identity and a regular UNIX login name may have the same textual representation (and in most cases they do for ease of use), but it is important to understand that they are two different beings. The default is to have them be the same, if the SE Linux identity in question exists. Therefore, if I log in as user faye on an SE Linux system, and if the policy database has the identity faye compiled into it, then my processes would be assigned to the faye identity.

To illustrate that standard UNIX user IDs are different from SE Linux identities, consider the su command. Running su does not change the user identity under SE Linux, but it does change the uid in the same way it would on a non-SE Linux system. If user faye, on the SE Linux system, types su - to switch to root and then runs the id command, which returns her security context and other information, she would see that her identity still is faye and not root, but her uid has changed. To illustrate this further, if an unprivileged user with the login name faye runs the id command, she would see the security context of:

uid=1000(faye) gid=1000(faye)
groups=1000(faye) context=faye:user_r:user_t
sid=45

The identity portion of the security context in this case is faye. Notice the uid of 1000. Next, say faye does an su to root and runs the id command again; she now would see:

uid=0(root) gid=0(root) groups=0(root)
context=faye:user_r:user_t sid=453

The identity has not changed to root as might be expected, but the uid has changed to 0. However, if user faye has been granted access to enter the superuser role, or sysadm_r, she can do so by either logging in at the console and specifying she wants the superuser role or entering the newrole -r command covered later. If she then runs the id command again, she now sees context=3Dfaye:sysadm_r:sysadm_t.

So again, the identity remains the same, but the role and domain (second and third fields, respectively) have changed. Maintaining the identity in this manner is useful where user accountability is required. It also is crucial to system security because the user identity determines what roles and domains can be used. With regular UNIX, if you have a setuid or setgid program that is not world-executable, whether it is executed is determined not by the permissions of the user you are logged in as, but by the user you last did an su to reach. This restriction does not exist under SE Linux, as your identity is tracked throughout all operations. If your domain has not been granted the access to execute that setuid/setgid program, you cannot run it even if you did an su to root. The domains you are permitted to enter are determined by your role, and the roles you are permitted to enter are determined by your identity. Thus, identity indirectly controls the list of domains you may enter.

Type: each object has a type assigned to it, and that type determines what can access the object. Objects here are files, directories, sockets and other processes. A type is similar in concept to a domain, the difference being that a domain applies only to processes. More specifically, a domain is a type that can be applied to a process.

Transition: a transition refers to the change in security context for a requested operation. Transitions fall into one of two categories. The first category is a transition of process domains. When you execute a program of a given type, a transition may be made from the current domain of the process to a new domain. To illustrate this, I'll use the newrole command. The newrole command is used to change your role, say, from user_r to sysadm_r, assuming you have been granted access to sysadm_r. If you start off as user_r, the general unprivileged user role, and run newrole -r sysadm_r to change to sysadm_r, the system administrator role, a transition is made from your user_t domain to newrole_t (the domain in which the newrole process runs) and from there on to the sysadm_t domain.

The second transition category is the transition of file type when you create a file under a particular directory. If a user creates a file in his own home directory, that file is labeled as user_home_t. But if that same user creates a file in /tmp, that file is labeled user_tmp_t. user_tmp_t is derived from the type of /tmp, which is tmp_t, and the domain of the creating process, which is user_t. When the user creates a file under /tmp, a transition to the user_tmp_t type is made.

Policies: a policy determines what actions can be taken on various types by various domains. All dæmons have their own policies, and the naming convention is of the form dæmon-name.te—postfix.te, apache.te and so forth. As the system administrator of an SE Linux machine, you can edit your policy files to suit your requirements. The policy database is a compiled form of the policy source files and is loaded by the kernel at boot time.

The spasswd program on an SE Linux system is used to change your password. spasswd actually is a wrapper for the standard passwd command used on Linux systems; it ensures that the passwd program is run in the correct domain. It also ensures that your SE Linux identity matches your regular UNIX account name. Earlier I mentioned that regular UNIX user IDs are quite different from SE Linux identities, so why do they have to match when running spasswd? spasswd requires you to have the same SE Linux identity name as your UNIX account name. Recall that on an SE Linux system, your identity is the only unique method of determining who you are. So if you're not currently the corresponding UNIX user, you cannot change the password.

If you are the system administrator user (sysadm_r), the sadminpasswd program is used to change the password of another user. sadminpasswd does not have the same matching user name/identity restriction that spasswd has, but sadminpasswd can be run only by sysadm_t.

Permissive and Enforcing Modes

SE Linux can be run in one of two modes, permissive or enforcing. Permissive mode is used for debugging purposes as everything gets logged, but SE Linux is not actually enforcing your policies. You still can do things as root that you could do on a regular Linux system. It is best to run your machine in permissive mode until you are satisfied that all your policies are correct. Labels are assigned to objects on the system, but nothing is enforced.

Enforcing mode applies the policies you have configured, such as access restrictions. You should boot in to enforcing mode only when you are convinced that everything is working properly, after running in permissive mode for a while. Remember, if your kernel is compiled with no development support, you cannot specify permissive mode. If your kernel is compiled with development mode support turned on, it means that your machine boots into permissive mode, but you have to switch it to enforcing mode manually. This can be done easily by creating a startup script.

Alternatively, you can make a link between /etc/rc.boot/avc and /sbin/avc_toggle. Another option is to specify enforcing=1 on the kernel command line. The avc_toggle command can be used to switch between permissive and enforcing mode, and the avc_enforcing command can be used to determine whether you are in enforcing mode.

Where to Go from Here

Hopefully this article has you interested in trying out SE Linux. I have omitted installation instructions deliberately, as you can install with RPMs, source tarballs or Debian packages. Including even the basics of each here would fill an entire article. There's quite a lot to learn before, during and after installation, and new users often find themselves rather confused. If you read the documents referred to in the Resources section before you do anything else and become familiar with frequently used terms, you should find it a little easier. If you get stuck, fire up your favorite IRC client and go over to channel #selinux on irc.debian.org, or subscribe to the SE Linux mailing list.

Faye Coker currently works as a freelance systems administrator and often finds herself running the systems at ISPs and converting servers to Linux. She has worked in Europe and Australia. She also has been asked “are you lost?” far too many times at Linux conferences.