NB Imp SELinux-aware Apps

From SELinux Wiki
Jump to: navigation, search

Implementing SELinux-aware Applications

Introduction

The following definitions attempt to explain the difference between the two types of userspace SELinux application (however the distinction can get 'blurred'):

SELinux-aware - Any application that provides support for SELinux. This generally means that the application makes use of SELinux libraries and/or other SELinux applications. Example SELinux-aware applications are the Pluggable Authentication Manager (PAM(8)) and SELinux commands such as runcon(1). It is of course possible to class an object manager as an SELinux-aware application.

Object Manager - Object Managers are a specialised form of SELinux-aware application that are responsible for the labeling, management and enforcement[1] of the objects under their control.

Generally the userspace Object Manager forms part of an application that can be configured out should the base Linux OS not support SELinux.

Example userspace Object Managers are:

  • X-SELinux is an optional X-Windows extension responsible for labeling and enforcement of X-Windows objects.
  • Dbus has an optional Object Manager built if SELinux is defined in the Linux build. This is responsible for the labeling and enforcement of Dbus objects.
  • SE-PostgreSQL is an optional extension for PostgreSQL that is responsible for the labeling and enforcement of PostgreSQL database and supporting objects.

Therefore the basic distinction is that Object Managers manage their defined objects on behalf of an application, whereas general SELinux-aware applications do not (they rely on 'Object Managers' to do this e.g. the kernel based Object Managers such as those that manage filesystem, IPC and network labeling).

Implementing SELinux-aware Applications

This section puts forward various points that may be useful when developing SELinux-aware applications and object managers using libselinux.

  1. Determine the security objectives and requirements.
  2. Because these applications manage labeling and access control, they need to be trusted.
  3. Where possible use the libselinux *_raw functions as they avoid the overhead of translating the context to/from the readable format (unless of course there is a requirement for a readable context - see mcstransd(8)).
  4. Use selinux_set_mapping(3) to limit the classes and permissions to only those required by the application.
  5. The standard output for messages generated by libselinux functions is stderr. Use selinux_set_callback(3) with SELINUX_CB_LOG type to redirect these to a log handler.
  6. Do not directly reference SELinux configuration files, always use the libselinux path functions to return the location. This will help portability as SELinux has some changes in the pipe-line for the location of the policy configuration files and the SELinux filesystem.
  7. Where possible use the selabel_*(3) functions to determine a files default context as they effectively replace the matchpathcon*(3) series of functions - see selabel_file(5).
  8. Do not use class IDs directly, use string_to_security_class(3) that will take the class string defined in the policy and return the class ID/value. Always check the value is > 0. If 0, then signifies that the class is unknown and the deny_unknown flag setting in the policy will determine the outcome of any decision - see security_deny_unknown(3).
  9. Do not use permission bits directly, use string_to_av_perm(3) that will take the permission string defined in the policy and return the permission bit mask.
  10. Where performance is important when making policy decisions (i.e. using security_compute_av(3), security_compute_av_flags(3), avc_has_perm(3) or avc_has_perm_noaudit(3)), then use the selinux_status_*(3) functions to detect policy updates etc. as these do not require system call over-heads once set up. Note that the selinux_status_* functions are only available from libselinux 2.0.99, with Linux kernel 2.6.37 and above.
  11. Be aware that applications being built for 32 bit systems need to specify the CFLAG -D_FILE_OFFSET_BITS=64 as libselinux is built with this flag. This is particularly important if matchpathcon_filespec_add(3) is used as it passes over ino_t ino that is too small otherwise (i.e. needs to be 64 bits).
  12. There are changes to the way contexts are computed for sockets in kernels 2.6.39 and above as described in the Computing Security Contexts section. The functions affected by this are: avc_compute_create(3), avc_compute_member(3), security_compute_create(3), security_compute_member(3) and security_compute_relabel(3).
  13. It is possible to set an undefined context if the process has capability(7) CAP_MAC_ADMIN and class capability2 with mac_admin permission in the policy. This is called 'deferred mapping of security contexts' and is explained at:
http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=12b29f34558b9b45a2c6eabd4f3c6be939a3980f

Implementing Object Managers

To implement object managers for applications, an understanding of the application is essential, because as a minimum:

  • What object types and their permissions are required.
  • Where in the code object instances are created.
  • Where access controls need to be applied.

While this section cannot help with those points, here are some notes to help during the design phase:

  1. Determine what objects are required and the access controls (permissions) that need to be applied.
  2. Does SELinux already have some of these object classes and permissions defined. For standard Linux OS objects such as files, then these would be available. If so, the object manager should remap them with selinux_set_mapping(3) so only those required are available. However, do not try to reuse a current object that may be similar to the requirements, it will cause confusion at some stage. Always generate new classes/permissions.
  3. If the application has APIs or functions that integrate with other applications or scripts, then as part of the object manager implementation these may need to support the use of security contexts (examples are X-Windows and SE-PostgreSQL that provide functions for other applications to use). Therefore if required, provide common functions that can be used to label the objects.
  4. Determine how the initial objects will be labeled. For example will a configuration file be required for default labels, if so how will this be introduced into the SELinux userspace build. Examples of these are the X-Windows (selabel_x(5)), SE-PostgreSQL (selabel_db(3)), and file context series of files (selabel_file(5)).
  5. Will the labeling need to be persistent across policy and system reloads or not. X-Windows is an example of a non-persistent, and SE-PostgreSQL is an example of a persistent object manager.
  6. Will support for the standard audit log or its own be required (the libselinux functions default to stderr). Use selinux_set_callback(3) to manage logging services.
  7. Decide whether an AVC cache is required or not. If the object manager handles high volumes of requests then an AVC will be required.
  8. Will the object manager need to do additional processing when policy or enforcement changes are detected. This could be clearing any caches or resetting variables etc.. If so, then selinux_set_callback(3) will be used to set up these functions. These events are detected via the netlink(7) services, see avc_open(3) and avc_netlink_open(3) for the various options available.
  9. If possible implement a service like XACE for the application, and use it to interface with the applications SELinux object manager. The XACE interface acts like the LSM which supports SELinux as well as other providers such as SMACK. The XACE interface is defined in the "X Access Control Extension Specification", and for reference, the SE-PostgreSQL service also implements a similar interface.

The XACE specification is available from:

http://www.x.org/releases/X11R7.5/doc/security/XACE-Spec.pdf

Reference Policy Changes

When adding a new object manager to SELinux, it will require at least a new policy module to be added. This section assumes that the SELinux Reference Policy is in use and gives some pointers, however any detail is beyond the scope of this section. Further information can be found at:

https://github.com/TresysTechnology/refpolicy/wiki

The latest Reference Policy source can be obtained as follows:

git clone https://github.com/TresysTechnology/refpolicy.git

The main points to note when adding to the Reference Policy are:

  • Create sample Reference Policy policy modules (*.te, *.if and *.fc module files) that provide rules for managing the new objects as described in the Reference Policy Module Files section.
The SE-PostgreSQL modules provide an example, see the ./refpolicy/policy/modules/services/postgresql.* files in the Reference Policy source.
Note, that if no new object classes, permissions or constraints are being added to the policy, then the Reference Policy source code does not require modification, and supplying the module files (*.te, *.if and *.fc) should suffice.
  • Create any constraints required as these need to be built into the base module of the Reference Policy. They are added to the ./refpolicy/policy/constraints, mcs and mls files. Again the SE-PostgreSQL entries in these files give examples (find the db_* class entries).
  • Create any SELinux configuration files (context, user etc.) that need to be added to the policy at build time.
  • Either produce an updated Reference Policy source or module patch, depending on whether new classes/constraints have been added. Note that by default a new module will be generated as a 'module', if it is required that the module is in the base (unusual), then add an entry <required val='true'> to the start of the interface file as shown below:
## <summary>
##Comment regarding interface file
## </summary>
## <required val="true">
##Comment on reason why required in base
## </required>

Adding New Object Classes and Permissions

Because userspace object managers do not require their new classes and permissions to be built into the kernel, the configuration is limited to the actual policy (generally the Reference Policy) and the application object manager code. New classes are added to the Reference Policy security_classes file and permissions to the access_vectors file.

The class configuration file is at:

 ./refpolicy/policy/flask/security_classes

and each entry must be added to the end of the file in the following format:

class object_name        # userspace

Where class is the class keyword and object_name is the name of the object. The # userspace is used by build scripts to detect userspace objects.

The permissions configuration file is at:

 ./refpolicy/policy/flask/access_vectors

and each entry must be added to the end of the file in the following format:

class object_name
{
    perm_name
    [........]
}

Where class is the class keyword, object_name is the name of the object and perm_name is the name given to each permission in the class (there is a limit of 32 permissions within a class). It is possible to have a common permission section within this file, see the file object entry in the access_vectors file for an example.

The same principle applies to adding new class/permissions to Android although the flask files are located in the external/sepolicy directory.

Note that CIL policies do not use flask files and class/permissions must be declared using the class, classpermission, and classorder statements (see the device/demo_vendor/cil_device/external/cil_sepolicy/classes_and_perms.cil file in the Notebook tarball).

For reference, http://selinuxproject.org/page/Adding_New_Permissions describes how new kernel object classes and permissions are added to the system and is summarised as follows for kernels >= 2.6.33 that use dynamic class/perm discovery:

  • Edit security/selinux/include/classmap.h in the kernel tree and add the required definition. This will define the class and/or permission for use in the kernel; the corresponding symbol definitions will be automatically generated during the kernel build. If not defined in the policy, then the class and/or permission will be handled in accordance with the policy's handle_unknown definition, which can be reject (refuse to load the policy), deny (deny the undefined class/permission), or allow (allow the undefined class/permission). handle_unknown is set to allow in Fedora policies.
  • Edit refpolicy/policy/flask/security_classes and/or access_vectors in the refpolicy tree and add your definition. This will define the class and permission for use in the policy. These are generally added to the class and/or permission at the end of the existing list of classes or permissions for that class for backward compatibility with older kernels. The class and/or permission definition in policy need not line up with the definition in the kernel's classmap, as the values will be dynamically mapped by the kernel. Then add allow rules as appropriate to the policy for the new permissions.

The email thread http://marc.info/?l=seandroid-list&m=139056956927985&w=2 describes how the CAN sockets could be added to the kernel along with possible hooks required in security/selinux/hooks.c.


Previous
Home
Next



  1. The SELinux security server does not enforce a decision, it merely states whether the operation is allowed or not according to the policy. It is the object manager that enforces the decision of the policy / security server, therefore an object manager must be trusted. This is also true of labeling, the object manager ensures that labels are applied to their objects as defined by policy.