Difference between revisions of "NB Objects"

From SELinux Wiki
Jump to: navigation, search
(Labeling Subjects)
Line 362: Line 362:
 
----
 
----
 
<references/>
 
<references/>
 +
 +
[[Category:Notebook]]

Revision as of 20:47, 13 September 2010

Objects

Within SELinux an object is a resource such as files, sockets, pipes or network interfaces that are accessed via processes (also known as subjects). These objects are classified according to the resource they provide with access permissions relevant to their purpose (e.g. read, receive and write), and assigned a security context as described in the following sections.

Object Classes and Permissions

Each object consists of a class identifier that defines its purpose (e.g. file, socket) along with a set of permissions[1] that describe what services the object can handle (read, write, send etc.). When an object is instantiated it will be allocated a name (e.g. a file could be called config or a socket my_connection) and a security context (e.g. system_u:object_r:selinux_config_t) as shown in the Object Class diagram.

The objective of the policy is to enable the user of the object (the subject) access to the minimum permissions needed to complete the task (i.e. do not allow write permission if only reading information).

These object classes and their associated permissions are built into the GNU / Linux kernel and user space object managers by developers and are therefore not generally updated by policy writers.

The object classes consist of kernel object classes (for handling files, sockets etc.) plus user space object classes used by user space object managers (for services such as the name service cache daemon (nscd), X-Windows and debus). The number of object classes and their permissions can vary depending on the features configured in the GNU / Linux release. The F-12 object classes and permissions are described in Object Classes and Permissions.

Allowing a Process Access to Resources

This is a simple example that attempts to explain two points:

  1. How a process is given permission to use an objects resource.
  2. By using the "process" object class, show that a process can be described as a process or object.

An SELinux policy contains many rules and statements, the majority of which are allow rules that (simply) allows processes to be given access permissions to an objects resources.

The following allow rule and the allow rule diagram illustrates "a process can also be an object" as it allows processes running in the unconfined_t domain, permission to "transition" the external gateway application to the ext_gateway_t domain once it has been executed:

allow Rule | source_domain  |  target_type : class   | permission
-----------x----------------x------------------------x--------------
allow        unconfined_t    ext_gateway_t : process   transition;

Where:

allow The SELinux language allow rule.
unconfined_t The source domain (or subject) identifier - in this case the shell that wants to exec the gateway application.
ext_gateway_t The target object identifier - the object instance of the gateway application process.
process The target object class - the "process" object class.
transition The permission granted to the source domain on the targets object - in this case the unconfined_t domain has transition permission on the ext_gateway_t "process" object.


It should be noted that there is more to a domain transition than described above, for a more detailed explanation, see the Domain Transition section.

Labeling Objects

Within a running SELinux enabled GNU / Linux system the labeling of objects is managed by the system and generally unseen by the users (until labeling goes wrong !!). As processes and objects are created and destroyed, they either:

  1. Inherit their labels from the parent process.
  2. The policy type_transition statements allow a different label to be assigned as discussed in the Domain and Object Transitions section.
  3. SELinux-aware applications can enforce a new label (with the policies approval of course) using the libselinux API functions.
  4. The object manager (OM) can enforce a default label that can either be built into the OM or obtained via a configuration file (such as the X-Windows x_contexts file).
  5. Use an "initial security identifier" (or initial SID). These are defined in all base and monolithic policies and are used to either set an initial context during the boot process, or if an object requires a default (i.e. the object does not already have a valid context).

While the majority of objects are managed via the system automatically using either the inherited label or an initial SID as required, there are objects that need to have labels defined for them either by their OM (bullet 4 above) using configuration files[2] or by using policy language statements.

The SELinux policy language supports object labeling statements for file and network services that are defined in the File System Labeling Statements and Network Labeling Statements sections.

An overview of the process required for labeling files systems that use extended attributes (such as ext3 and ext4) is discussed in the next section.

Labeling Extended Attribute Filesystems

The labeling of file systems that implement extended attributes[3] is supported by SELinux using:

  1. The fs_use_xattr statement within the policy to identify what file systems use extended attributes. This statement is used to inform the security server how the file system is labeled.
  2. A "file contexts" file that defines what the initial contexts should be for each file and directory within the file system. The format of this file is described in the Policy Configuration Files [4] section.
  3. A method to initialise the filesystem with these extended attributes. This is achieved by SELinux utilities such as fixfiles(8) and setfiles(8). There are also commands such as chcon(1), restorecon(8) and restorecond(8) that can be used to relabel files.

Extended attributes containing the SELinux context of a file can be viewed by the ls -Z or getfattr(1) commands as follows:

ls -Z myfile
-rw-r--r-- root root unconfined_u:object_r:admin_home_t:s0 myfile
getfattr -n security.selinux <file_name>

#file_name: rpmbuild
security.selinux="unconfined_u:object_r:admin_home_t:s0\000"

# Where -n security.selinux is the name of the attribute and
# rpmbuild is the file name.
# The security context (or label) for the file is:
# system_u:object_r:admin_home_t:s0

Copying and Moving Files

Assuming that the correct permissions have been granted by the policy, the effects on the security context of a file when copied or moved differ as follows:

  • copy a file - takes on label of new directory unless the -Z option is used.
  • move a file - retains the label of the file.

However, if the restorecond daemon is running and the restorecond.conf file is correctly configured, then other security contexts can be associated to the file as it is moved or copied (provided it is a valid context and specified in the /etc/selinux/<policy_name>/contexts/files/file_contexts file.

The examples below show the effects of copying and moving files:

# These are the test files in the /root directory and their current security
# context:
#
-rw-r--r-- root root user_u:object_r:unconfined_t copied-file
-rw-r--r-- root root user_u:object_r:unconfined_t moved-file

# These are the commands used to copy / move the files:
#
# Standard copy file:
cp copied-file /usr/message_queue/in_queue

# Copy using -Z to set the files context:
cp -Z user_u:object_r:unconfined_t copied-file /usr/message_queue/in_queue/copied-file-with-Z

# Standard move file:
mv moved-file /usr/message_queue/in_queue

# The target directory (/usr/message_queue/in_queue) is label "in_queue_t".
# The results of "ls -Z" on target the directory are:
#
-rw-r--r-- root root user_u:object_r:in_queue_t copied-file
-rw-r--r-- root root user_u:object_r:unconfined_t copied-file-with-Z
-rw-r--r-- root root user_u:object_r:unconfined_t moved-file

However, if the restorecond daemon is running:

# If the restorecond daemon is running with a restorecond.conf file entry of:
#
/usr/message_queue/in_queue/*

# AND the file_context file has an entry of:
#
/usr/message_queue/in_queue(/.*)? -- system_u:object_r:in_file_t

# Then all the entries would be set as follows when the daemon detects the files
# creation:
#
-rw-r--r-- root root user_u:object_r:in_file_t copied-file
-rw-r--r-- root root user_u:object_r:in_file_t copied-file-with-Z
-rw-r--r-- root root user_u:object_r:in_file_t moved-file

# This is because the restorecond process will set the contexts defined in 
# the file_contexts file to the context specified as it is created in the 
# new directory.

This is because the restorecond process will set the contexts defined in the file_contexts file to the context specified as it is created in the new directory.

Labeling Subjects

On a running GNU / Linux system, processes inherit the security context of the parent process. If the new process being spawned has permission to change its context, then a "type transition" is allowed that is discussed in the Domain Transition section.

The Initial Boot - Loading the Policy section discusses how GNU / Linux is initialised and the processes labeled for the login process.

The policy language supports a number of statements to either assign labels to processes such as:

  • user, role and type statements.

and manage their scope:

  • role allow and constrain

and manage their transition:

  • type_transition, role_transition and range_transition

One point to note is that the current Reference Policy does not support role transitions / changes as these are "constrained" by the policy. To change to a different role, the newrole(1) command needs to be used.

Object Reuse

As GNU / Linux runs, it creates instances of objects and manages the information they contain (read, write, modify etc.) under the control of processes, and at some stage these objects may be deleted or released allowing the resource (such as memory blocks and disk space) to be available for reuse.

GNU / Linux handles object reuse by ensuring that when a resource is re-allocated, it is cleared. This means that when a process releases an object instance (e.g. release allocated memory back to the pool, delete a directory entry or file), there may be information left behind that could prove useful if harvested. If this should be an issue, then the process itself should clear or shred the information before releasing the object (which can be difficult in some cases unless the source code is available).

Domain and Object Transitions

This section discusses the type_transition Statement that is used for:

  1. Transition a process from one domain to another (a domain transition).
  2. Transition an object from one type to another (an object transition or relabel).

These transitions can also be achieved using the [LibselinuxAPISummary | libselinux API] functions, however they are beyond the scope of this Notebook as is dynamically changing a processes security context using the dyntransition permission.

Domain Transition

A domain transition is where a process in one domain, transitions to another domain (i.e. runs under a different security context). There are two ways a process can request a domain transition in a policy:

  • Using a type_transition statement to perform a domain transition for programs that are not themselves SELinux-aware. This is the most common method and would be in the form of the following statement:
type_transition unconfined_t secure_services_exec_t : process ext_gateway_t;
  • SELinux-aware applications can specify the domain of the new process using the [LibselinuxAPISummary | libselinux API] call setexeccon. To achieve this the SELinux-aware application must also have the setexec permission by:
allow crond_t self : process setexec;

However, before any domain transition can take place the policy must specify that:

  • The source domain has permission to transition into the target domain.
  • The application binary file needs to be executable in the source domain.
  • The application binary file needs an entry point into the target domain.

The following is a type_transition statement taken from the example loadable module message filter ext_gateway.conf (described in volume 2) that will be used to explain the transition process[5]:

type_transition | source_domain | target_type           : class | target_domain;
----------------x---------------x-----------------------x----------------------
type_transition   unconfined_t   secure_services_exec_t : process ext_gateway_t;

This type_transition statement states that when a process running in the unconfined_t domain (the source domain) executes a file labeled secure_services_exec_t, the process should be changed to ext_gateway_t (the target domain) if allowed by the policy (i.e. transition from the unconfined_t domain to the ext_gateway_t domain).

However, as stated above to be able to transition to the ext_gateway_t domain, the following minimum permissions must be granted in the policy using allow rules], where (note that the bullet numbers correspond to the numbers shown in the Domain Transition diagram):

1) The domain needs permission to transition into the ext_gateway_t (target) domain:

allow unconfined_t ext_gateway_t : process transition;

2) The executable file needs to be executable in the unconfined_t (source) domain, and therefore also requires that the file is readable:

allow unconfined_t secure_services_exec_t : file { execute read getattr };

3) The executable file needs an entry point into the ext_gateway_t (target) domain:

allow ext_gateway_t secure_services_exec_t : file entrypoint;

These are shown in the Domain Transition diagram where unconfined_t forks a child process, that then exec's the new program into a new domain called ext_gateway_t. Note that because the type_transition statement is being used, the transition is automatically carried out by the SELinux enabled kernel.


Type Enforcement Rules

When building the ext_gateway.conf and int_gateway.conf modules (described in Volume 2) the intention was to have both of these transition to their respective domains via type_transition statements. The ext_gateway_t statement would be:

type_transition unconfined_t secure_services_exec_t : process ext_gateway_t;

and the int_gateway_t statement would be:

type_transition unconfined_t secure_services_exec_t : process int_gateway_t;

However, when linking these two loadable modules into the policy, the following error was given:

semodule -v -s modular-test -i int_gateway.pp -i ext_gateway.pp
Attempting to install module 'int_gateway.pp':
Ok: return value of 0.
Attempting to install module 'ext_gateway.pp':
Ok: return value of 0.
Committing changes:
libsepol.expand_terule_helper: conflicting TE rule for (unconfined_t, secure_services_exec_t:process): old was ext_gateway_t, new is int_gateway_t
libsepol.expand_module: Error during expand
libsemanage.semanage_expand_sandbox: Expand module failed
semodule: Failed!

This happened because the type enforcement rules will only handle a single "default" type for a given source and target. In the above case there were two type_transition statements with the same source and target, but different target domains. The ext_gateway.conf module had the following statements:

# Allow the client/server to transition for the gateways:
allow unconfined_t ext_gateway_t : process { transition };
allow unconfined_t secure_services_exec_t : file { read execute getattr };
allow ext_gateway_t secure_services_exec_t : file { entrypoint };
type_transition unconfined_t secure_services_exec_t : process ext_gateway_t;

And the int_gateway.conf module had the following statements:

# Allow the client/server to transition for the gateways:
allow unconfined_t int_gateway_t : process { transition };
allow unconfined_t secure_services_exec_t : file { read execute getattr };
allow int_gateway_t secure_services_exec_t : file { entrypoint };
type_transition unconfined_t secure_services_exec_t : process int_gateway_t;

While the allow rules are valid to enable the transitions to proceed, the two type_transition statements had different "default" types, that break the type enforcement rule.

It was decided to resolve this by:

  1. Keeping the type_transition rule for the "default" type of ext_gateway_t and allow the secure server process to be execed from unconfined_t<tt> as shown in the Domain Transition diagram, by simply running the command from the prompt as follows:
# Run the external gateway "secure server" application on port 9999 and 
# let the policy transition the process to the ext_gateway_t domain:

secure_server 99999
  1. Use the SELinux <tt>runcon(1) command to ensure that the internal gateway runs in the correct domain by running runcon from the prompt as follows:
# Run the internal gateway "secure server" application on port 1111 and 
# use runcon to transition the process to the int_gateway_t domain:

runcon -t int_gateway_t -r message_filter_r secure_server 1111

# Note - The role is required as a role transition is also defined in the
# policy.

The runcon command makes use of a number of [LibselinuxAPISummary | libselinux API] functions to check the current context and set up the new context (for example getfilecon is used to check the executable files context and setexeccon is used to ensure the setexec permission is allowed). If the all contexts are correct, then the execvp(2) system call is executed that exec's the secure_server application with the argument of "1111" in the int_gateway_t<tt> domain with the <tt>message_filter_r role. The runcon source can be found in the coreutils package.

Other ways to resolve this issue are:

  1. Use the runcon command for both gateways to transition to their respective domains. The type_transition statements are therefore not required.
  2. Use different names for the secure server executable files and ensure they have a different type (i.e. instead of secure_service_exec_t label the external gateway ext_gateway_exec_t and the internal gateway int_gateway_exec_t. This would involve making a copy of the application binary (which has already been done as part of the module testing (see volume 2) by calling the server “server” and labeling it unconfined_t and then making a copy called secure_server and labeling it secure_services_exec_t).
  3. Implement the policy using the Reference Policy template interface.

It was decided to use runcon as it demonstrates the command usage better than reading the man page.

Object Transition

An object transition is where an object needs to be relabeled, for example changing a files label from one type to another. There are two ways this can be achieved within policy:

1) Using a type_transition Statement to perform an object transition (relabel) for programs that are not SELinux-aware. This is the most common method and would be in the form of the following statement:

type_transition ext_gateway_t in_queue_t:file in_file_t;

2) Using a type_change Statement to perform an object transition for programs that are SELinux-aware.

type_change sysadm_t server_ptynode : chr_file sysadm_devpts_t;

The libselinux API call security_compute_relabel would be used to compute the new context.

The following details an object transition used in the ext_gateway.conf loadable module (shown in volume 2) where by default, files would be labeled in_queue_t when created by the gateway application as this is the label attached to the parent directory as shown:

ls -Za /usr/message_queue/in_queue
drwxr-xr-x root root user_u:object_r:in_queue_t .
drwxr-xr-x root root system_u:object_r:unconfined_t ..

However the requirement is that files in the in_queue directory must be labeled in_file_t. To achieve this the files created must be relabeled to in_file_t by using a type_transition rule as follows:

# type_transition | source_domain | target_type : object | default_type;
------------------x---------------x----------------------x---------------
type_transition    ext_gateway_t    in_queue_t  : file      in_file_t;

This type_transition statement states that when a process running in the ext_gateway_t domain (the source domain) wants to create a file object in the directory that is labeled in_queue_t, the file should be relabeled in_file_t if allowed by the policy (i.e. label the file in_file_t).

However, as stated above to be able to relabel the file, the following minimum permissions need to be granted in the policy using allow rules, where:

  • The source domain needs permission to add file entries into the directory:
allow ext_gateway_t in_queue_t : dir { write search add_name };
  • The source domain needs permission to create file entries:
allow ext_gateway_t in_file_t : file { write create getattr };
  • The policy can then ensure (via the SELinux kernel services) that files created in the in_queue are relabeled:
type_transition ext_gateway_t in_queue_t:file in_file_t;

An example output from a directory listing shows the resulting file labels:

ls -Za /usr/message_queue/in_queue
drwxr-xr-x root root user_u:object_r:in_queue_t .
drwxr-xr-x root root system_u:object_r:unconfined_t ..
-rw-r--r-- root root user_u:object_r:in_file_t Message-1
-rw-r--r-- root root user_u:object_r:in_file_t Message-2



  1. Also known in SELinux as Access Vectors (AV).
  2. The advantage of defining labels in an OM configuration file and not in the policy language is that the OM can then be used by other security mechanisms (for example NetLabel can be used by the Simplified Mandatory Access Control Kernel (SMACK) as this MAC system also hooks into the LSM).
  3. These file systems store the security context in an attribute associated with the file.
  4. Note that this file contains the contexts of all files in all extended attribute filesystems for the policy. However within a modular policy each module describes its own file context information, that is then used to build this file.
  5. For reference, the external gateway uses a server application called secure_server that is transitioned to the ext_gateway_t domain from the unconfined_t domain. The secure_server executable is labeled secure_services_exec_t.