User:SwifT/selinux-tutorials/2

How SELinux controls file and directory accesses
In the previous tutorial, we learned that SELinux adds in another method for finding out what the privileges would be for a process: a security context. This security context, together with the run-time user that the process is in, would define what the process is allowed to do.

When most users hear about controlling access on a Linux system, they immediately think about allowing file and directory access. It is tangible, a real-life scenario and simple to imagine or even reproduce. So let's talk about how SELinux would control file and directory access - we'll talk about the various other resources that SELinux can control later.

File access on Linux, without SELinux
Let's rewind a bit, and consider file access on a Linux system, but without any additional access control methods.

Access to files and directories is governed through the process' run-time user, the file/directory owner information and permission bits. With ls -l, or the more verbose stat, you can get information about the file ownership and permission bits. Let's consider the following output (ignore the Context bit from stat for now).

What this information tells us, is that the torrc file is owned by the root Linux user, part of the root Linux group, and that both the owner (root), group (root) and other users can read it (the r bit is set). Only the owner (root Linux user) has write access to the file (the w bit is set). So access-wise, a process that runs as a non-root user will be able to read the file, but not write to it.

So when something (a process, called the actor) tries to write (which is a permission) to the file /etc/tor/torrc (which is called the resource), Linux checks the access controls and denies the request. The permissions that are in scope for the standard Linux access controls are the well-known read/write/execute rights, and they are based on the process ownership and file ownership.

This file access control is very standard on Linux, and should be well known by administrators and users. When looking at the file (or directory) ownership, it should be immediately obvious for users what can and cannot happen against the file. Consider the /var/cache/gorg directory:

In the above example, you should immediately notice that - unless a process is running as the gorg user, or within the gorg group - no process has access to this directory. Well, none is wrong: root-owned processes can still get into the directory and manipulate it (as root is the all-powerful user). Or the /var/lib/slocate directory:

Here, root-running processes can write into the directory, and processes that are running within the "locate" group can read/access the directory. Other processes will not be able to, as shown by the next attempt (by a regular user process) to enter this directory:

What users like you and me do in order to know what would or wouldn't be allowed, is to check the actor information (in this case, the run-time user, which is a regular user account), the resource information (in this case, the ownership details for the file) and then match the permission we want to check (like entering a directory) against the allowed permissions (execute in this case).

SELinux-ifying the examples
Before going towards SELinux itself, let's first write the above examples in a policy-like language.

Let's start with the /etc/tor/torrrc file, which had the following information (meta-data):

We could write the access controls against this file as follows:
 * Allow any process that runs as the root Linux user to read the torrc file
 * Allow any process that runs as the root Linux user to write to the torrc file
 * Allow any process that runs within the root group to read the torrc file
 * Allow any process to read the torrc file

Or with the slocate directory:

This could be written as:
 * Allow any process that runs as the root Linux user to read the slocate directory information
 * Allow any process that runs as the root Linux user to write into the slocate directory (create files and such)
 * Allow any process that runs as the root Linux user to enter the slocate directory (and thus search for files within)
 * Allow any process that runs within the locate group to read the slocate directory information
 * Allow any process that runs within the locate group to enter the slocate directory

Although quite verbose, this does tell you exactly what the permissions are on the torrc file or slocate directory.

What SELinux uses are a construction very much similar to the lines above. To control access to files, SELinux would write such lines as follows:

allow root_user torrc:file { read write }; allow root_group torrc:file { read }; allow any_process torrc:file { read }; allow root_user slocate:dir { read write execute }; allow slocate_group slocate:dir { read write };
 * 1) For torrc file
 * 1) For slocate directory

Of course, the used labels don't make much sense yet, but you can notice the syntax already.

allow  : { };

What SELinux does, is to define type enforcement rules: you define what an actor (defined by its ) can do ( ) against the resource () of a particular type/class (). Understanding this is very important. SELinux is primarily a type enforcement implementation, so you define what something can do against something else.