Security Enhanced Linux a.k.a SELinux
September 21, 2010 Leave a comment
Writing about this topic is gruelling one. I am greatly influenced by the articles mentioned in the resources section at bottom of this article.Just trying to put things together for the avid user to read at a glance.So without much ado we shall start getting into the fact quickly which will give you head start.
But before we dive in ,we must make sure that we have enable the kernel option of the SELinux.So it look like in the .config file of the kernel source below:
When configuring your kernel do the following: (Under Networking Options, enable Network Packet Filtering. Under Security Options, enable Capabilities and enable both IP Networking and SELinux as built-in options.) This means having the following in your /usr/src/linux/.config: CONFIG_NETFILTER=y CONFIG_INET=y CONFIG_SECURITY=y CONFIG_SECURITY_CAPABILITIES=y CONFIG_SECURITY_SELINUX=y CONFIG_SECURITY_DTE=n CONFIG_SECURITY_OWLSM=n CONFIG_LIDS=n This release of SE Linux depends on XATTR's. For the Ext3 file system use the following settings: CONFIG_EXT3_FS_XATTR=y CONFIG_EXT3_FS_XATTR_SHARING=y CONFIG_EXT3_FS_SECURITY=y The options CONFIG_EXT3_FS_XATTR_USER and CONFIG_EXT3_FS_XATTR_TRUSTED are not required for SE Linux, but do not do any harm either.
Why SE Linux?
SE Linux offers greater security for your system. Users can be assigned predefined roles so that they can not access files or processes that they do not own. There is no “chmod 777” equivalent operation. This differs from regular Unix permissions in that the user defined roles, or security contexts they are placed in, have limited access to files and other resources but in a far more controlled fashion. Take a user’s .rhosts file on a regular Unix system. If they make it world writeable then anyone can login and do lots of damage. Under SE Linux, you can control whether or not the user has the ability to change the permissions on their .rhosts file, and also prevent other people from writing to it even after the owner has made it world writeable.
A common question is how SE Linux permissions relate to standard Unix permissions. When you do a certain operation, the Unix permissions are checked first. If they allow your operation then SE Linux will check next and allow or deny as appropriate. But if the Unix permissions don’t let you do something, the requested operation stops there and the SE Linux checks aren’t performed.
Another example is if there was an exploitable bug in /usr/bin/passwd which could run chmod 666 /etc/shadow SE Linux permissions would still prevent anyone from inappropriately accessing the file.
Terminology used in this parlance
An identity under SE Linux is not the same as the traditional Unix uid (user id). They can coexist together on the same system, but are quite different. identities under SE Linux form part of a security context which will affect what domains can be entered, i.e. what essentially can be done. An SE Linux identity and a standard Unix login name may have the same textual representation (and in most cases they do), however it is important to understand that they are two different things. Running the su command does not change the user identity under SE Linux.
An unprivileged user with the login name faye runs the id command (under SE Linux) and sees the security context of
The identity portion of the security context in this case is “faye”. Now, if faye su’s to root and runs id, she will see the security context is still
so the identity remains the same, and has not changed to root. However, if identity faye has been granted access to enter the sysadm_r role and does so (with the newrole -r command which will be covered later), and runs id command again, she will now see
So 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 is also crucial to system security in that the user identity will determine what roles and domains can be used.
Every process runs in a domain. A domain directly determines the access a process has. A domain is basically a list of what processes can do, or what actions a process can perform on different types. Think of a domain like a standard Unix uid. Say root has a program and does a chmod 4777 on that program (making it setuid root). Anyone on the system, even the nobody user, can run this program as root thereby creating a security issue. With SE Linux however, if you have a process which triggers a domain transition to a privileged domain, if the role of the process is not authorised to enter a particular domain, then the program can’t be run.
Some examples of domains are sysadm_t which is the system administration domain, and user_t which is the general unprivileged user domain. init runs in the init_t domain, and named runs in the named_t domain.
A type is assigned to an object and determines who gets to access that object. The definition for domain is roughly the same, except a domain applies to process and a type applies to objects such as directories, files, sockets, etc.
A role determines what domains can be used. The domains that a user role can access are predefined in policy configuration files. If a role is not authorised to enter a domain (in the policy database), then it will be denied.
In order to allow a user from the user_t domain (the unprivileged user domain) to execute the passwd command, the following is specified in the relevant config file:
role user_r types user_passwd_t
It shows that a user in the user role (user_r) is allowed to enter the user_passwd_t domain i.e. they can run the passwd
A security context has all the attributes that are associated with things like files, directories, processes, TCP sockets and so forth. A security context is made up of the identity, role and domain or type. You can check your own current security context by running id under SE Linux.
There is a very important distinction which needs to be made here, between a domain and a type, as it tends to cause a little confusion later on if you don’t understand it from the start.
Processes have a domain. When you check the security context of a process (for an example, see the explanation of “transition”, below), the final field is the domain such as user_passwd_t (if you were running the passwd command).
Objects such as files, directories, sockets etc have types. When you use the ls –context command on a file for instance, the final field is the type, such as user_home_t for a file created in the home directory of a user in the user_r role.
Here’s where a little confusion can creep in, and that’s whether something is a domain or a type. Consider the /proc filesystem. Every process has a domain, and /proc has directories for each process. Each process has a label, or rather, a security context applied to a file. But in the /proc world, the label contains a type, and not a domain. Even though /proc is representing running processes, the entries under /proc are considered files and therefore have a type instead of a domain.
Running ls –context /proc shows the following listing for the init process (with a process id of 1):
dr-xr-xr-x root root system_u:system_r:init_t 1
The label, or security context, shows that this file has a type of init_t However it also means that the init process is running in the init_t domain. Each file or directory under /proc that has a process id for a filename will follow this convention, i.e. the type listed for that process in the output of a ls –context command will also be the domain that process is running in.
Another thing to note is that commands such as chsid (change the security id) and chcon (change context) don’t work on /proc as /proc does not support changing of labels.
The security context of a file, for example, can vary depending on the domain that creates it. By default, a new file or directory inherits the same type as its parent directory, however you can have policies set up to do otherwise.
user faye creates a file named test in her home directory. She then runs the command ls –context test and sees
-rw-r--r-- faye faye faye:object_r:user_home_t test
She then creates a file in /tmp called tmptest and runs the command ls –context /tmp/tmptest This time, the result is
-rw-r--r-- faye faye faye:object_r:user_tmp_t /tmp/tmptest
In the first example, the security context includes the type “user_home_t” which is the default type for the home directory of an unprivileged user in the user_r role. After running the second ls –context command, you can see that the type is user_tmp_t which is the default type that is used for files created by a user_t process, in a directory with a tmp_t type.
A transition decision, also referred to as a labelling decision, determines which security context will be assigned for a requested operation. There are two main types of transition. Firstly, there is a transition of process domains which is used when you execute a process of a specified type. Secondly, there is a transition of file type used when you create a file under a particular directory.
For the second type of transition (transition of file type), refer to the example give in the “security context” section above. When running the ls –context commands you can see what the file types are labelled as (i.e. user_home_t and user_tmp_t in the above examples). So, here you can see that when the user created a file in /tmp a transition to the user_tmp_t domain occurred and the new file has been labelled as such.
For transition of process domains, consider the following example. Run ssh as a non privileged user, or more specifically, from the user_t domain (remember you can use the id command to check your security context). Then run ps ax –context and note what is listed for ssh. Assuming user faye does this, she sees
as part of the output listing. The ssh process is being run in the user_ssh_t domain because the executable is of type ssh_exec_t and the user_r has been granted access to the user_ssh_t domain.
Policies are a set of rules governing things such as the roles a user has access to; which roles can enter which domains and which domains can access which types. You can edit your policy files according to how you want your system set up.
Studying the SELinux policy
SELinux makes access decisions based on the security contexts assigned to processes, files, and other objects. SELinux provides interfaces for querying these contexts and, given the required access rights, to set them. For instance, SELinux reports process contexts through the
procattr interface. If you type:
You can see the context of the current process (
$$). You can easily view the context of all processes on the system.
Most operating systems use access controls to determine whether an entity (user or program) can access a given resource. UNIX®-based systems use a form of discretionary access control (DAC). This method restricts access to objects based commonly on the groups to which they belong. For examples, files in GNU/Linux have an owner, a group, and a set of permissions. The permissions define who can access a given file, who can read it, who can write to it, and who can execute it. These permissions are split into three sets of users, representing the user (owner of the file), the group (all users who are members of a group), and others (all users who are neither members of the group nor owner of the file).
Lumping access controls like this creates a problem because an exploited program inherits the access controls of the user. Thus the program can do things at the user’s access level, which is undesirable. Rather than define restrictions this way, it’s more secure to use the principle of least privilege: programs can do what they need to perform their task, but nothing more. For example, if you have a program that responds to socket requests but doesn’t need to access the file system, then that program should be able to listen on a given socket but not have access to the file system. That way, if the program is exploited in some way, its access is explicitly minimized. This type of control is called mandatory access control (MAC).
Another approach to controlling access is role-based access control (RBAC). In RBAC, permissions are provided based on roles that are granted by the security system. The concept of a role differs from that of a traditional group in that a group represents one or more users. A role can represent multiple users, but it also represents the permissions that a set of users can perform.
SELinux adds both MAC and RBAC to the GNU/Linux operating system. The next section explores the SELinux implementation and how security enforcement was transparently added to the Linux kernel.
Should you really disable SELinux?
Be aware that by disabling SELinux you will be removing a security mechanism on your system. Think about this carefully, and if your system is on the Internet and accessed by the public, then think about it some more. Joshua Brindle (an SELinux developer) has comments on disabling SELinux here, which states clearly that applications should be fixed to work with SELinux, rather than disabling the OS security mechanism.
You need to decide if you want to disable SELinux temporarily to test the problem, or permanently switch it off. It may also be a better option to make changes to the policy to permit the operations that are being blocked – but this requires knowledge of writing policies and may be a steep learning curve for some people. For the operating system as a whole, there is two kinds of disabling:
- Permissive – switch the SELinux kernel into a mode where every operation is allowed. Operations that would be denied are allowed and a message is logged identifying that it would be denied. The mechanism that defines labels for files which are being created/changed is still active.
- Disabled – SELinux is completely switched off in the kernel. This allows all operations to be permitted, and also disables the process which decides what to label files & processes with.
Disabling SELinux could lead to problems if you want to re-enable it again later. When the system runs with file labelling disable it will create files with no label – which could cause problems if the system is booted into Enforcement mode. A full re-labelling of the file system will be necessary.
You can switch the system into permissive mode with the following command:
echo 0 >/selinux/enforce
You’ll need to be logged in as root, and in the sysadm_r role:
newrole -r sysadm_r
To switch back into enforcing mode:
echo 1 >/selinux/enforce
In Fedora Core and RedHat Enterprise Linux you can use the setenforce command with a 0 or 1 option to set permissive or enforcing mode, its just a slightly easier command than the above.
To check what mode the system is in,
which will print a “0” or “1” for permissive or enforcing – probably printed at the beginning of the line of the command prompt.
The above will switch off enforcement temporarily – until you reboot the system. If you want the system to always start in permissive mode, then here is how you do it.
In Fedora Core and RedHat Enterprise, edit /etc/selinux/config and you will see some lines like this:
# This file controls the state of SELinux on the system. # SELINUX= can take one of these three values: # enforcing - SELinux security policy is enforced. # permissive - SELinux prints warnings instead of enforcing. # disabled - No SELinux policy is loaded. SELINUX=enforcing # SELINUXTYPE= can take one of these two values: # targeted - Only targeted network daemons are protected. # strict - Full SELinux protection. SELINUXTYPE=targeted
… just change SELINUX=enforcing to SELINUX=permissive, and you’re done. Reboot if you want to prove it.
For the other Linuxes which don’t have the /etc/selinux/config file, you just need to edit the kernel boot line, usually in /boot/grub/grub.conf if you’re using the GRUB boot loader. On the kernel line, add enforcing=0 at the end. For example,
title SE-Linux Test System root (hd0,0) kernel /boot/vmlinuz-2.4.20-selinux-2003040709 ro root=/dev/hda1 nousb enforcing=0 #initrd /boot/initrd-2.4.20-selinux-2003040709.img
Fully disabling SELinux goes one step further than just switching into permissive mode. Disabling will completely disable all SELinux functions including file and process labelling.
In Fedora Core and RedHat Enterprise, edit /etc/selinux/config and change the SELINUX line to SELINUX=disabled:
# This file controls the state of SELinux on the system. # SELINUX= can take one of these three values: # enforcing - SELinux security policy is enforced. # permissive - SELinux prints warnings instead of enforcing. # disabled - No SELinux policy is loaded. SELINUX=disabled # SELINUXTYPE= can take one of these two values: # targeted - Only targeted network daemons are protected. # strict - Full SELinux protection. SELINUXTYPE=targeted
… and then reboot the system.
For the other Linuxes which don’t have the /etc/selinux/config file, you just need to edit the kernel boot line, usually in /boot/grub/grub.conf, if you’re using the GRUB boot loader. On the kernel line, add selinux=0 at the end. For example,
title SE-Linux Test System root (hd0,0) kernel /boot/vmlinuz-2.4.20-selinux-2003040709 ro root=/dev/hda1 nousb selinux=0 #initrd /boot/initrd-2.4.20-selinux-2003040709.img
You will have to reboot to disable SELinux, you just can’t do it while the system is running.
If you’ve disabled SELinux as in the section above, and you want to enable it again then you’ve got a bit of work to do. The problem will be that files created or changed when SELinux was disabled won’t have the correct file labels on them – if you just reboot in enforcing mode then a lot of stuff won’t work properly.
What you need to do is to enable SELinux by editing /etc/selinux/config (for Fedora/RedHat) or by adding selinux=1 to the kernel boot line, then boot into permissive mode, then relabel everything, and then reboot into (or simply switch to) enforcing mode.
After booting into permissive mode, run :
Alternatively, in Fedora and RedHat Enterprise Linux you can run touch /.autorelabel and reboot or put autorelabel on the boot command line – in both cases the file system gets a full relabel early in the boot process. Note that this can take quite some time for systems with a large number of files.
After relabelling the filesystem, you can switch to enforcing mode (see above) and your system should be fully enforcing again.
Understanding SELinux modes
Irrespective of the policy or the rules implemented through SELinux Type Enforcement, there are three modes of operation for SELinux:
Disabled mode implies that SELinux is disabled and not implemented on the host. This has been the most common choice in installations seen by me. Hopefully, by the end of this series, we shall be able to bring about a change in that practice by encouraging more system administrators to adopt SELinux.
Permissive mode is similar to Debugging Mode. In Permissive Mode, SELinux policies and rules are applied to subjects and objects, but actions (for example, Access Control denials) are not effected. The biggest advantage of Permissive Mode is that log files and error messages are generated based on the SELinux policy implemented.
In other words, if the SELinux policy would prevent the
httpd subject (Apache Web server) from accessing the object folder
/webdata on my system, implementing SELinux in Permissive Mode would let the Apache Web server access the folder
/webdata but log a denial in the log files.
This error logging informs the system administrator that if SELinux is activated in the Enforcing Mode, the httpd subject would be disallowed access to the /webdata folder on my system.
Permissive Mode is the initiating point for all those wanting to explore the world of Type Enforcement through SELinux. Without blocking access to your favourite programs such as OpenOffice.org, Evolution, etc, it provides you with enough debugging information to fine tune your policy before deploying it on your system.
Enforcing Mode, as the name signifies, is SELinux in action. All production systems, when hardened, should enable SELinux in Enforcing Mode. SELinux through Access Controls does have a minor performance overhead, but compared to the advantages that it brings to the table, I am sure it will soon become the norm to implement SELinux on production servers.
Now few mundane thing to know about the SELinux thing on the system . Here are things:
Check the status of SELinux:
bhaskar@bhaskar-laptop_08:06:39_Tue Sep 21:~> sudo sestatus
[sudo] password for bhaskar:
SELinux status: enabled
SELinuxfs mount: /selinux
Current mode: enforcing
Mode from config file: enforcing
Policy version: 24
Policy from config file: targeted
Get the information about the policy:
bhaskar@bhaskar-laptop_08:15:48_Tue Sep 21:~> sudo getenforce
The file you need to look in for SElinux in RHEL system is located at /etc/sysconfig/selinux.You can get into this file through any editor and change/edit your preferences.By default, there are two policies shipped along with Red Hat Enterprise Linux: Targeted and Strict.
The Targeted Policy is the first step in assisting system administrators to understand and implement SELinux. It only ‘targets’ certain network daemons such as the Apache Web server, FTP server, BIND DNS server and a few others, while leaving the vast majority of end-user applications largely untouched. It creates an ‘unconfined’ domain ‘confinement’ (interesting paradox, isn’t it?) and does not apply Access Control Restrictions to most applications in the unconfined domain.
The Strict Policy, on the other hand, is a true restrictive Access Control Policy. Before implementing this policy, make sure you understand SELinux concepts and policies well.
How to manage context?
There is binary called “semanage” which will do the job for us. So here we go to get the details:
bhaskar@bhaskar-laptop_08:38:02_Tue Sep 21:~> sudo semanage fcontext -l | less
SELinux fcontext type Context
/ directory system_u:object_r:root_t:s0
/.* all files system_u:object_r:default_t:s0
/[^/]+ regular file system_u:object_r:etc_runtime_t:s0
/\.autofsck regular file system_u:object_r:etc_runtime_t:s0
/\.autorelabel regular file system_u:object_r:etc_runtime_t:s0
/\.journal all files <<None>>
/\.suspended regular file system_u:object_r:etc_runtime_t:s0
/a?quota\.(user|group) regular file system_u:object_r:quota_db_t:s0
/afs directory system_u:object_r:mnt_t:s0
…..output snipped for the sake of clarity.
Change context temporarily:
How do you do that? SELinux comes with a binary called “chcon“,by which we will made this possible.So here is implication of it:
bhaskar@bhaskar-laptop_08:42:42_Tue Sep 21:~> sudo touch /tmp/change_context
[sudo] password for bhaskar:
bhaskar@bhaskar-laptop_08:48:45_Tue Sep 21:~> ls -lZ /tmp/change_context
-rw-r–r–. root root unconfined_u:object_r:user_tmp_t:s0 /tmp/change_context
Here I have created an empty file on /tmp and listing the default context attached with it.Now we are going to change it:
root@bhaskar-laptop_08:52:11_Tue Sep 21:~ # chcon -t unconfined_t /tmp/change_context
root@bhaskar-laptop_08:52:37_Tue Sep 21:~ # ls -Z /tmp/change_context
Restorecon: the healer
Now if something goes wrong about it then we can get back the thing by running “restorecon” on the affected files and directories
root@bhaskar-laptop_09:51:42_Tue Sep 21:/home/bhaskar # restorecon -v /fileODir_goes_bad
Hope this will help.