This tutorial explains SELinux in detail with examples including SELinux modes, SELinux file context, SELinux policy and how to run web server with SELinux.
SELinux is the security implementation which enhances system security and in the event of security breach, it stops that from spreading in entire system. Before we understand SELinux in details, let’s take an example to figure out why do we need the SELinux?
Suppose we are running a web server which hosts several websites. To allow access on websites we have to open several ports in firewall. Hackers may use these ports to crack the system through the security exploits. And if that happens, hackers will gain the access permission of web server process. To serve web pages, usually a web server process has read permission on document root and write permission on the /tmp and /var/tmp directory. With this permission, hackers can write malicious scripts in /tmp directory which can be used to hack other services available on server. This way one infected process can cause a huge security rick to all services running on server.
If SELinux is enabled, hackers will not be able to access the other services available on sever as well as they will not be able to write anything in /tmp or /var/tmp directory.
How SELinux should interact with Linux is defined in SELinux mode. So, let's start learning SELinux with this foundation topic.
SELinux works in three modes; Disable, Permissive and Enforcing. In disable mode SELinux remains completely disable. If SELinux is enabled, it will be in either Permissive mode or in Enforcing mode. In permissive mode SELinux will only monitor the interaction. In enforcing mode SELinux will also filter the interaction with monitoring.
Let’s take an example. Suppose an ftp user want to access his home directory. So he accesses the shell prompt and executes the following command
At LinuxServer system following will happen: -
- A SysCall (System Call) will be generated for FTP server.
- If SELinux is disabled, SysCall will be processed normally.
- If SELinux is enabled, all Syscall will be processed through it.
- SELinux will log the Syscall in /var/log/audit/audit.log file.
- If SELinux enable mode is set to Permissive, Syscall will be processed normally.
- If SELinux enable mode is set to Enforcing, Syscall will be checked against the security policies and will be processed only if it has the required permission.
Following figure illustrates this process step by step
To view the current status (enable or disable) and current mode (disable, permissive and enforcing) of SELinux we can use sestatus command
As above output indicates, SELinux is enabled and currently working in enforcing mode. For troubleshooting purpose, SELinux allows us to switch between Enforcing and Permissive mode in current session. For example, an ftp user is not able to access his home directory and we want to know whether this issue is related with SELinux or not. To figure out the answer we can switch SELinux to permissive mode from enforcing mode.
If ftp user is able to access the home directory in permissive mode but not in enforcing mode, then we can assume that SELinux is blocking the ftp user. But if ftp user is not able to access the home directory in permissive mode then we can be sure that issue is not related with SELinux as SELinux doesn’t block anything in permissive mode.
To switch between permissive mode and enforcing mode we can use setenforce command. The setenforce 0 command is used to put SELinux in permissive mode and setenforce 1 command is used to put the SELinux in enforcing mode.
Let’s put SELinux in permissive mode
To confirm the switch, we can use sestatus command again or we can use getenforce command (The getenforce command prints only the name of current mode).
Let’s put SELinux in enforcing mode again
Following figure illustrates above process step by step
SELinux doesn’t allow us to switch between enable (enforcing or permissive) and disable mode in running session. A system restart is required to switch between these modes. SELinux modes are stored in /etc/sysconfig/selinux file. To switch between enable and disable mode we have to update the default value of SELinux mode in this file. Let’s have a look on this file.
Linux reads this configuration file at startup to find out the default mode of SELinux.
If this value is set to enforcing or permissive, Linux will load the necessary libraries for SELinux.
If this value is set to disable, Linux will not load any libraries associated with SELinux.
For this reason, we are not allowed switch between enable and disable mode in running session.
To understand it more clearly let’s put the SELinux in disabled mode.
Access the /etc/sysconfig/selinux file and update the default SELinux mode value and save the file and restart the system.
Following figure illustrates this process step by step
After restart confirm that SELinux is disabled.
As I mentioned earlier, if default SELinux mode is set to disabled, boot process will not load any libraries associated with SELinux and without necessary libraries we cannot enable the SELinux. Let’s try to enable it.
As output indicates we are not allowed to switch from disable mode to enable mode in running session. Let’s put SELinux back in enforcing mode.
- SELinux works in three modes; disable, permissive and enforcing.
- In Disable mode SELinux will not interfere in any system call.
- In Permissive mode SELinux will log each system call but it will not filter any access request.
- In Enforcing mode SELinux will log each system call and filter it with configured security policies. Based on security policy SELinux will decide whether it should allow the request or deny the request.
- SELinux mode are stored in /etc/sysconfig/selinux file.
- By default, enforcing mode is set to default mode.
- Linux boot process checks default SELinux mode from /etc/sysconfig/selinux file. If default mode is set to permissive or enforcing, boot process will load the necessary libraries for SELinux. If default mode is set to disable, boot process will skip all libraries associated with SELinux.
- We can switch between enforcing and permissive mode in running session. Switching between enable (enforcing and permissive) and disable mode requires a system reboot.
- If SELinux is disabled, nothing will go through the SELinux. If SELinux is enabled, everything will through the SELinux.
RHCSA/RHCE exams have an essential requirement “Exam system must be configured with SELinux in enforcing mode”. To meet with this requirement, you should not put the SELinux in disable mode. If you want to disable the SELinux temporary, switch it to permissive mode.
Is starting of this tutorial we took an example of web server process Where I stated “If SELinux is enabled, hackers will not be able to access the other services available in server as well as they will not be able to write anything in /tmp or /var/tmp directory”. So how will SELinux protect the system from a rogue application?
To protect the system SELinux uses the policy. A SELinux policy is basically a set of rules that defines which process can access which files, directories and ports. With this rules set an application will be able to access only the certain types of files and process which it requires to function, nothing extra.
So, how does SELinux know that which application require which file types?
SELinux policies are written by the application developers. And application developers know what exactly their application will do and what types of files it needs to work. For example, Apache (Linux web Sever) application developers know what kinds of files and what kinds of permission on that files are required by Apache web server to run. So they created necessary rules for Apache Web Sever in SELinux policy. This way other application developers also created necessary rules for their applications.
SELinux uses context to identify the associated resources with an application or process.
A context is the collection of security related information assigned on each object (file, directory, application, port, process etc.) of Linux file system. SELinux uses context to make access control decision.
To view the context of an object we can use Z flag with regular listing command. Let’s take couple of examples.
To view the context of files and directories we can Z flag with ls –l command.
To view the context of network port we can use Z flag with netstat –tulpen command
To view the contexts of running process we can use Z flag with ps aux command
As we can see in above outputs every context always consists of four parts; user part, role part, type part and sensitivity part. Each part is separated by a colon (:). Let’s understand these parts one by one.
This is the first part. It ends with _u in the context label. In context label it represents SELinux user account. As we know all users, process or applications do not need same level of permission. Some accounts need more permission while some accounts need less permission. To manage the level of permission SELinux uses user accounts.
- SELinux user accounts are different form Linux user accounts.
- Unlike Linux user accounts, we are not allowed to create SELinux user accounts at shell prompt with commands.
- SELinux users are defined in SELinux policy and load in memory at boot time.
- SELinux users do not have login access to server.
- SELinux uses user accounts to define the multiple level of permission.
- Each Linux user account is mapped with a SELinux user account. SELinux does this mapping in policy.
SELinux user context is not included RHCSA or RHCE exams. While preparing for exam, please pay attention only on the type part of the context. Do not spend time in learning user, role and sensitivity part as these are not tested in RHCSA and RHCE exam.
This is the second part in security context label. It ends with _r. In SELinux policy role defines what a subject can do with an object in specified domain.
- A subject is a user or a daemon or a process which access the object.
- An object is a resource (such as file, directory, process, hardware device or network application) which is accessed by subject.
- A domain defines what a subject can do and what it can’t do. It is just like a bubble around the subject.
This is third part in security context. It ends with _t. This part defines what kind of object is it. For example, a type for file defines what kind of file is it such as /etc directory file, web page file, hardware device file or network file. Since Type is the only part which is tested in RHCE exam, we will understand this part in detail with examples (shortly in practice section).
This is fourth and last part of security context. This part defines multiple layer of security between level c0 and c3. The C3 is defined as “Top Secret”, and levels in this range goes up to c1023. This part is used only when SELinux policy type is set to MLS mode. MLS mode is developed for the departments which require very high level of security such as Military, Department of Defense, etc. Such a fine-grained security model usually does not require in regular data server. For regular data server Targeted mode with appropriate Booleans provides more than adequate security.
We interacted with two new words here; SELinux policy mode and Booleans. So what are these? We will understand Booleans in next part of this article. In this tutorial let’s understand what is SELinux policy mode.
SELinux policy mode
SELinux policy modes control the behavior of SELinux. Basically there are two modes; MLS and targeted. We have already discussed MLS mode. Now let’s quickly understand the targeted mode.
Targeted mode is the default mode in RHEL. In this mode SELinux targets only the selected process. Selected processes run in confined domains. Remaining all processes run in unconfined domain. For instance, httpd process is the example of targeted process and logged in user is the example of unconfined process.
SELinux policy modes are also controlled by the same file which control the SELinux mode.
Unless you have any specific requirement, do not change SELinux policy mode. Especially if you are preparing for RHCE exam.
So far in this article we have discussed essential SELinux topics in detail. In remaining part, we will take some particle examples of SELinux.
Web Server Setup for SELinux practice
For this tutorial I assume that httpd service is installed and running in practice system. If httpd service is not installed, install it with yum command.
#yum install httpd
To start this service use following command
#systemctl start httpd
Create a index.html file in default document root (/var/www/html) with following contents.
<h1>RHCE LAB </h1> <b> This is the test file</b>
Now access this file from web browser. If GUI is install, use Firefox web browser otherwise use elinks command at shell prompt.
Following figure illustrates above process step by step
This is the essential setup which we need for practice. If you are able to access the test (index.html) web page from browser, go ahead with practice. If you are unable to access the test web page from browser, please check your httpd configuration.
For this tutorial I assume that you are able to access the test web page.
SELinux Practical Examples
Okay let’s move back in home directory and create two files; test1.html and test2.html with some simple dummy contents such as “This is an example web page. If you can see this web page, then web server is able to read the test.html file”.
Now copy the first file (test1.html) and move the second file (test2.html) in default document root (/var/www/html) directory.
Now access both web pages from browser.
We are allowed to access the first web page (test1.html) and that’s fine. But what went wrong with second web page?
Let’s figure out step by step.
- We created a web page in default document root and we were able to see the web page.
- We created a web page in home directory and copied it in default document root and again we were able to see the web page.
- We created a web page in home directory and moved it in default document root and this time we were denied to see the web page. So definitely something fishy happened when we moved the file. What was that? To find out, let’s repeat the process again.
Delete both files (test1.html and test2.html) from both locations (home directory and web document root) and confirm the delete operation.
#rm -f test1.html #ls #cd /var/www/html/ #rm –f test1.html #rm –f test2.html #ls
Move back in home directory and create both files again. Before we copy or move these files in documents root, let’s make a note of associated security context. Now copy and move the files again in document root and check the security context there.
Have you notice any difference in security context?
When we copied the file, its type context changed. While when we moved the file, its type context remain unchanged. So is this type context which is blocking web server from accessing this file?
Yes, you catch it right.
As we discussed earlier, if SELinux is enabled, everything will go through it. When web server accesses files, SELinux checks whether the web server has access right on targeted file or not.
A web server process is allowed access the files which have httpd_sys_content_t type context. In above example test2.html is the only file which has different security context. That’s why our web server was unable access the test2.html file.
- When we create a new file, SELinux applies appropriate security attributes on file based on its location.
- In copy operation, original file remains at source location and a new file is created at destination. Since a new file is being created at destination, file will get security attributes based on destination.
- In move operation, original file is moved from source to destination. Since nothing new is created at destination, file will be placed at destination with its original attributes.
We have three possible solutions of above problem; create the new file in document root, use copy operation or update the security context of moved file. We have already seen first two options, let’s discuss third option.
Update the type context
We have two commands to update the SELinux context; chcon and semanage.
The chcon command updates context directly in file system. This is the fastest way to update the SELinux context. The chcon command uses following syntax: -
chcon [options] CONTEXT FILE
Following table lists some common options which can be used with this command
|-R||Apply changes recursively|
|-v||Provides verbose output|
|-u||Sets user context|
|-r||Sets role context|
|-t||Sets type context|
Let’s update the type context of file test2.html with this command and access test2.html web page again from browser
Bingo! we can access the blocked page now. But wait we are not going to use this command. This command may lead us to failure in RHCE exam.
As this command updates security context in file system not in SELinux policy. Everything which we changed with this command will be overwritten when the file system is relabeled or original contexts are restored from policy to file system.
Let’s understand it with an example
Move back in home directory and create a dummy file with some dummy data. Note down its type context. Since we have created this file in root directory which is owned by root user, its type security context would be admin_home_t. Change type context to user_home_t with chcon command and verify the change. Now run restorecon command and view the context again. Is change still preserved? Nope… its gone. File got its original security context back. This is what happen when we update security context with chchon command.
Following figure illustrates this example step by step
Now it’s clear that why we should not use the chcon command. But what is the alternative? And the answer is semanage command. Before we learn semange command, let’s understand what restorecon command do.
As we discussed earlier, SELinux has policy rules for all objects in Linux. Usually these rules define default locations for subject (user, process, application), from where the subject can access the associated files.
So, when we create a new file, SELinux compares the location with its database to figure out, which subject (user, process, application) can access files form this location, based on result SELinux applies appropriate security contexts. The restorecon command also do the same job. For any reason if default security context of a file is changed, restorecon command will restore the original security context back to file.
File location plays major role in this process. Default security contexts work with default location. To understand it more clearly let’s extended previous example. In previous example default type context of the file is admin_home_t which we updated with user_home_t and later restored original context back with restorecon command.
Now let’s move this file on some other locations and use retstorecon command.
As we can see in above figure, restorecon command uses location (or in simple word the parent directory) to determine the default security context for a file.
When we moved the file in /var/www/html location and used restorecon command, the type context is updated with httpd_sys_content_t which make sense as this is the default document root for web server.
Later we moved back this file in root directory and used resotrecon command, the type context is being updated with admin_home_t which make sense again as this is default home directory for administrator account. In the same manner, when we restore the context in default home directory for user we got user_home_t type context.
So, if a process is running with default location, restorecon command is only what we need to set the correct type context. For instance, if our web server is running with default document root, regardless how we put the files there, all we need is following command to set the correct type context.
#restorecon –R –i -v /var/www/html
In above command we used following options: -
|-R||This option is used to restore the context recursively.|
|-i||This option is used to ignore the files which do not exist|
|-v||This option is used to show the real time changes.|
In real world things are not so easy. To meet the custom requirements, administrators customize Linux in several ways. For example, they may use a separate partition for user data or web data. In that case, we have to tell the SELinux that which directories or files belong to which subject. For this purpose, semange command is used.
Unlike chcon, the semanage command does not write anything in file system. Instead of file system the semanage command updates SELinux policy. As we know SELinux applies contexts on file system only at startup, so any change which we made in policy will apply at next time when SELinux will relabel the system. Luckily, we have restorecon command which can do this job in run time on file system or a portion of file system. We have already seen restorecon command in action, now let’s work with semanage command.
In our previous example, we worked with default web server setting. Now suppose due to any reason we want to use a non-default document root for our web server.
Let’s create one for testing
#mkdir /rhcelab #mkdir /rhcelab/customwebroot
By default, Apache (Default Web Server in RHEL Linux) uses default configuration setting. If we want to use something which is not default, then we have to update the corresponding setting in main configuration file. Let’s take the backup of original configuration file and open it in edit mode
#cp /etc/httpd/conf/httpd.conf /etc/httpd/conf/httpd.conf.original #vi /etc/httpd/conf/httpd.conf
Update the configuration setting as explained in following figure.
Since configuration file has been changed, we have to restart the web server so it can run with new configuration.
#systemctl restart httpd
Okay now let’s create our first web page with some simple text in new document root, check its security context and access this web page form web browser.
As we can see in above figure, we are not allowed to access the web page from new document root.
So, what went wrong? Well…… we updated the new document root in web server configuration file. But we did not tell the SELinux about this change. SELinux is still assuming that the directory /rhcelab/customwebroot belongs to the normal file system.
Notice the type context which file (testwebpage.html) received in new document root is completely different from the type context which files used to receive in default document root. And we know web server could not access the files which have different type context except httpd_sys_content_t.
Okay now we know the issue, let’s solve it.
Following command will update the SELinux about the change
#semanage fcontext -a –t httpd_sys_content_t “/rhcelab/customwebroot(/.*)?”
#restorecon –R –i /rhcelab/customwebroot/
Above two commands are very important for RHCE exam. Before we go further let’s understand these in detail.
First command tells SELinux that the directory /rhcelab/customwebroot belongs the web server process.
In first command
|Command /option/ parameter||Description|
|semange||This is the main command.|
|fcontext||This option tells main command that we want to change the context of file or directory.|
|-a||This option tells main command that we want to add the new context for specified file or directory.|
|-t||This option tells main command that we want to change the type context of specified file or directory with the type context specified in this command.|
|httpd_sys_content_t||This is the specified type context.|
|“/rhcelab/customwebroot(/.*)?”|| This is the specified file or directory. The (/.*)? is a regular file expression which matches every files and directories available under the specified directory. |
Replace /rhcelab/customwebroot/ with your own directory path.
In second command
|Command /option/ parameter||Description|
|restorecon||This is the main command|
|-R||This option tells command that we want to perform this operation recursively, starting from the specified directory.|
|-i||This option tells command to ignore the errors in operation.|
|/rhcelab/customwebroot/||This is the specified directory. Replace it with your own directory.|
In short first command updates SELinux policy in following pattern “Specified files or directories [“/rhcelab/customwebroot(/.*)?”] belong to specified type (httpd_sys_content_t) context ”.
Second command simply fetch the SELinux policy for specified directory and apply the changes.
Okay now let’s test whether we can access web page form new document root now or not.
This way whenever you change default root of any service, never forget to update the SELinux type context with following commands. Otherwise service will not be able to fetch the files or directories from new document root.
#semanage fcontext -a –t [Associated File Type Context] “NewDocumentRoot (/.*)?” #restorecon –R –i NewDocumentRoot
If you think above commands are hard to remember, you can use man page of semanage-fcontext command.
Type /example to navigate directly in example section. Here you will find above commands with examples how to use them.
Finding type context
The most difficult part of setting file type context is finding right context. And the easiest solution of this problem is looking in default document root. For example, to find out the right context for web server we looked in the default document root of web server (/var/www/html).
SELinux stores all contexts in /etc/selinux/targeted/contexts directory. Context for most regular files are stores file_contexts file.
Any contexts added through the semanage command are placed in file_contexts.local file.
We have finished our exercise let’s cleanup the changes
#cp /etc/httpd/conf/httpd.conf.original /etc/httpd/conf/httpd.conf #systemctl restart httpd
That’s all for this article. In next article we will learn SELinux Booleans in detail with examples.