This section gives an overview of the enhancements made to Android to produce Security Enhancements for Android&trade (SE for Android).

The main objective of this document is to provide a reference for the tools, commands, policy building tools and file formats of SE for Android based on the 4.4 release. The builds discussed are from AOSP master and SEAndriod master repositories (as July '14).

The white paper "An Overview of Samsung KNOX" also gives an overview of how SE for Android is being integrated with other security services (such as secure boot and integrity measurement) to help provide a more secure mobile platform.

This gives a high level view of the new and updated projects to support SE for Android services and covers AOSP with any additional SEAndroid functions noted. These are not a complete set of updates, but give some idea of the scope.

external/libselinux

Provides the SELinux userspace function library that is installed on the device. It is based on the Linux version but has additional functions to support Android, for example:

selinux_android_setcontext

Sets the correct domain context when launching applications using setcon(3). Information contained in the seapp_contexts file is used to compute the correct context.

It is called by frameworks/base/core/jni/com_android_internal_os_Zygote.cpp when forking a new process and the system/core/run-as/run-as.c utility.

selinux_android_setfilecon

Sets the correct context on application directory / files using setfilecon(3). Information contained in the seapp_contexts file is used to compute the correct context.

The function is used by the package installer within frameworks/native/cmds/installd/commands.c via the package install() and make_user_data() functions.

selinux_android_restorecon

selinux_android_restorecon_pkgdir

Basically these functions are used to label files and directories based on entries from the file_contexts and/or seapp_contexts files. They call a common handler (selinux_android_restorecon_common()) that will then relabel the requested directories and files. It will also handle recursive labeling of directories and files should a new app, file_contexts or seapp_contexts be installed (see the Checking File Labels section for further information).

The selinux_android_restorecon function is used by:

frameworks/native/cmds/installd/installd.c when installing a new app.

frameworks/base/core/jni/android_os_SELinux.cpp for the Java native_restorecon method.

Provides the policy userspace library. There are no specific updates to support SE for Android, also this library is not available on the device.

external/checkpolicy

Provides the policy build tool. Added support for MacOS X (darwin). Not available on the device as policy rebuilds are done in the development environment.

external/sepolicy

This is a policy specifically for the core components of SE for Android that looks much like the reference policy, but is contained in one directory that has the policy modules (*.te files), class / permission files etc.. The policy is built by the Android.mk file and the resulting policy is installed on the target device (as sepolicy) along with its supporting configuration files.

This is an Android application to manage the SE for Android environment (such as loading a new policy). Only available on SEAndroid build.

packages/apps/Settings

SELinux settings for the settings manager application.

bionic

Bionic is the Android libc that is a derived from the BSD standard C library code. It contains enhancements to support security providers such as SELinux.

bootable/recovery

Changes to manage file labeling on recovery.

build

Changes to build SE for Android and manage file labeling on images and OTA (over the air) target files.

frameworks/base

JNI - Add SELinux support functions such as isSELinuxEnabled and setFSCreateCon.

SELinux Java class and method definitions.

Checking Zygote connection contexts.

Managing file permissions for the package manager and wallpaper services.

SELinux additions to support install / run time MMAC and for SEAndroid the MMAC services.

system/core

SELinux support services for toolbox (e.g. load_policy, runcon).

SELinux support for system initialisation (e.g. init, init.rc).

SELinux support for auditing avc's (auditd).

system/extras

SELinux support for the ext4 file system. Note that the make_ext4fs utility is used to build these file systems and relies on the file_contexts file having all the relevant entries, if not, it will be unable to set the security.selinux xattr on the inode and fail.

kernel

There are a number of kernels that have been enhanced to support Linux Security Module (LSM) and SELinux services that are listed at:

Note that the Android kernels are based on various versions (currently 3.4 for Goldfish used by the emulator), therefore the latest SELinux enhancements may not always be present. The Kernel LSM / SELinux Support section describes the Andriod kernel changes.

device

Build information for each device, details regarding SEAndroid supported devices can be found at:

The paper "Security Enhanced (SE) Android: Bringing Flexible MAC to Android" available at http://www.internetsociety.org/sites/default/files/02_4.pdf gives a good review of what did and didn't change in the kernel to support Android. This section briefly describes the only major change that was to support the Binder IPC service that consists of the following:

LSM hooks in the binder code (drivers/staging/android/binder.c) and (include/linux/security.h)

Default support for capabilities (security/capability.c) in case no other module is loaded.

Hooks in the LSM security module (security/security.c).

SELinux support for the binder object class and permissions (security/selinux/include/classmap.h) that are shown in the SE for Android Classes and Permissions section. Support for these permission checks are added to security/selinux/hooks.c.

A subset of the Linux SELinux commands have been implemented in SE for Android and are listed in Table 1. They are available as Toolbox commands (see system/core/toolbox) and can be run via adb shell, for example:

adb shell su 0 setenforce permissive

Table 1: SELinux enabled adb shell commands (in Android toolbox)

Command

Comment

chcon

Change security context of file:

chcon context path

getenforce

Returns the current enforcing mode.

getenforce

getsebool

Returns SELinux boolean value(s):

getsebool [-a | boolean_name]

id

If SELinux is enabled then the security context is automatically displayed.

The public methods implemented are equivalent to libselinux functions and are show in Table 2. They have been taken from frameworks/base/core/java/android/os/SELinux.java.

The SELinux class and its methods are not available in the Android SDK, however if developing SELinux enabled apps within AOSP then reflection would be used (see the proguard.flags and Android.mk files in packages/apps/SEAdmin).

Table 2: SELinux class public methods

boolean isSELinuxEnabled()

Determine whether SELinux is enabled or disabled.

Return true if SELinux is enabled.

boolean isSELinuxEnforced()

Determine whether SELinux is permissive or enforcing.

Returns true if SELinux is enforcing.

boolean setSELinuxEnforce(boolean value)

Set whether SELinux is in permissive or enforcing modes.

value of true sets SELinux to enforcing mode.

Returns true if the desired mode was set.

boolean setFSCreateContext(String context)

Sets the security context for newly created file objects.

context is the security context to set.

Returns true if the operation succeeded.

boolean setFileContext(String path, String context)

Change the security context of an existing file object.

path represents the path of file object to relabel.

context is the new security context to set.

Returns true if the operation succeeded.

String getFileContext(String path)

Get the security context of a file object.

path the pathname of the file object.

Returns the requested security context or null.

String getPeerContext(FileDescriptor fd)

Get the security context of a peer socket.

FileDescriptor is the file descriptor class of the peer socket.

Returns the peer socket security context or null.

String getContext()

Gets the security context of the current process.

Returns the current process security context or null.

String getPidContext(int pid)

Gets the security context of a given process id.

pid an int representing the process id to check.

Returns the security context of the given pid or null.

String[] getBooleanNames()

Gets a list of the SELinux boolean names.

Return an array of strings containing the SELinux boolean names.

boolean getBooleanValue(String name)

Gets the value for the given SELinux boolean name.

name is the name of the SELinux boolean.

Returns true or false indicating whether the SELinux boolean is set or not.

boolean setBooleanValue(String name, boolean value)

Sets the value for the given SELinux boolean name. Note that this will be set the boolean permanently across reboots.

Restores a file to its default SELinux security context. If the system is not compiled with SELinux, then true is automatically returned. If SELinux is compiled in, but disabled, then true is returned.

pathname is the pathname of the file to be relabeled.

Returns true if the relabeling succeeded.

boolean restorecon(String pathname)

Restores a file to its default SELinux security context. If the system is not compiled with SELinux, then true is automatically returned. If SELinux is compiled in, but disabled, then true is returned.

pathname is the pathname of the file to be relabeled.

Returns true if the relabeling succeeded.

exception NullPointerException if the pathname is a null object.

boolean restorecon(File file)

Restores a file to its default SELinux security context. If the system is not compiled with SELinux, then true is automatically returned. If SELinux is compiled in, but disabled, then true is returned.

The Android init process language has been expanded to support SELinux as shown in Table 3. The complete Android init language description is available in the system/core/init/readme.txt file.

Table 3: SELinux init extensions

seclabel <securitycontext>

service option: Change to security context before exec'ing this service. Primarily for use by services run from the rootfs, e.g. ueventd, adbd. Services on the system partition can instead use policy defined transitions based on their file security context. If not specified and no transition is defined in policy, defaults to the init context.

restorecon <path>

action command: Restore the file named by <path> to the security context specified in the file_contexts configuration. Not required for directories created by the init.rc as these are automatically labeled correctly by init.

restorecon_recursive <path> [ <path> ]*

action command: Recursively restore the directory tree named by <path> to the security context specified in the file_contexts configuration. Do NOT use this with paths leading to shell-writable or app-writable directories, e.g. /data/local/tmp, /data/data or any prefix thereof.

action command: Set the current process security context to the specified string. This is typically only used from early-init to set the init context before any other process is started (see init.rc example above).

setenforce 0|1

action command: Set the SELinux system-wide enforcing status. 0 is permissive (i.e. log but do not deny), 1 is enforcing.

setsebool <name> <value>

action command: Set SELinux boolean <name> to <value>.

<value> may be 1|true|on or 0|false|off

Examples of their usage are shown in the following init.rc file segments:

Table 4 shows the SE for Android policy files with their default location when the device is built, and their alternate locations when devices are updated by other methods (such as OTA or via adb). The alternate locations are always checked first as if present they override the default location as discussed in the comments section of Table 4.

The init process will initially load the SELinux set of policy files from root (/). Once the /data partition setup has been completed (see init.rc) a policy reload is performed. This will check whether there is a valid policy at /data/security/current and load that if valid.

If safe mode, then only the root policy files will be loaded. A factory reset will wipe /data and will therefore revert to the original root policy files.

Table 4: Policy file locations

Default Location

Alternate Location

Comments

/sepolicy

/file_contexts

/seapp_contexts

/property_contexts

/service_contexts

/selinux_version

/mac_permissions.xml

/data/security/current

Any or all these files may be in the alternate directory as each conponent that requires them will look in the alternate first and then the default, however:

During a policy reload, if there is an selinux_version file in the alternate location, then the default location will be over-ridden. If the policy has been updated via the buildsebundle / SEAdmin app process then this would be the case.

The alternate directory may be a symbolic link to another directory. For example the buildsebundle / SEAdmin app process adds a link to /data/security/context that holds the policy files

If the policy has been updated via the buildsebundle / SEAdmin app process, then the following will also be present:

/data/security/bundle will contain the sepolicy_bundle (the packed files) and a metadata directory containing a version file holding the last version number.

There will be *_backup policy files of the previous version that could be restored if required.

This section covers building of SELinux MAC and Install-time MMAC policies. The file formats of SE for Android specific configuration files are detailed in the Policy File Configuration Details section with examples.

The policy files are contained in the external/sepolicy directory, however there may also be additional policy configuration files to enable specific device features under the device/<vendor>/<device>/sepolicy directory (see the Processing Device Policy section). Once generated the policy and its supporting configuration files are installed on the device as part of the build process.

The *.te files are the core policy module definition files. These are the same format as the standard reference policy and are expanded by the m4 macros. There is (generally) one .te file for each domain/service defined containing the policy rules.

These files will be installed on the device and used to compute SE for Android security contexts (see the Checking File Labels section for further information).

file_contexts

Contains default file contexts for setting the filesystem as Linux based SELinux (note that it does not contain entries for labeling apps or their data stores, the seapp_contexts file is used for that purpose). The format of this file is defined in file_contexts(5)</tt>. The file is installed by default in the root directory.SE for Android services (such as restorecon) will first check for this file at (this is where updated files would be placed):

/data/security/current/file_contexts

If not present they will then check the root directory:

/file_contexts

property_contexts

Contains default contexts for Android property services as discussed in the property_contexts File section. The file is installed by default in the root directory. The SE for Android initialisation / reload process will first check for this file at (this is where updated files would be placed):

/data/security/property_contexts

If not present they will then check the root directory:

/property_contexts

service_contexts

Contains default contexts for Android services as discussed in the service_contexts File section. The file is installed by default in the root directory. The SE for Android initialisation / reload process will first check for this file at (this is where updated files would be placed):

/data/security/service_contexts

If not present they will then check the root directory:

/service_contexts

seapp_contexts

Contains information to allow domain or file contexts to be computed based on parameters as discussed in the seapp_contexts File section. The file is installed by default in the root directory. The SE for Android initialisation / reload process will first check for this file at (this is where updated files would be placed):

/data/security/current/seapp_contexts

If not present they will then check the root directory:

/seapp_contexts

selinux-network.sh

This will not be processed by the SE for Android build, it must be specifically added to the device make file if required. See the selinux-network.sh Configuration section for details on configuring this file.

The following files will be built as part of the build process and installed on the device:

sepolicy

The kernel binary policy. The SE for Android initialisation / reload process will first check for this file at (this is where updated files would be placed):

The compiled kernel policy (sepolicy) is also in this directory along with policy.conf.dontaudit and sepolicy.dontaudit files that have the dontaudit rules removed.

sepolicy.recovery

A recovery policy is installed at system/etc/sepolicy.recovery. It is build with the macro target_recovery = true that will add additional rules defined in the recovery.te module (see Android.mk and te_macros). For reference the recovery policy text file is available at:

The selinux_version file is generated containing the BUILD_FINGERPRINT that the policy was built against. Its existence is used at boot time, policy upgrades or reloads to determine whether the policy configuration files should be read from /data/security/current or root (/). The mac_permissions.xml would also be read from either /data/security/current or /system/etc/security).

The Install-time MMAC is part of AOSP and SEAndroid policy build that is always enabled. The file that configures policy is mac_permissions.xml and its format is discussed in the Install-time MMAC Configuration File section. The file is installed by default at:

/system/etc/security/mac_permissions.xml

The SE for Android initialisation / reload process will first check for this file at:

/data/security/current/mac_permissions.xml

This file can be replaced through BOARD_SEPOLICY_REPLACE or appended to by the BOARD_SEPOLICY_UNION variable as described in the Processing Device Policy section.

This file can be updated along with all other MAC policy files as described in the Updating Policy section.

The main code for the service is frameworks/base/services/java/com/android/server/pm/SELinuxMMAC.java, however it does hook into other Android services. Note that AOSP and SEAndroid builds now support the same code base which was implemented by https://android-review.googlesource.com/#/c/80871. The change commit message is:

Prior support forced all third party apps to be resolved against the default stanza of the mac_permissions.xml file when assigning seinfo labels. This meant that all third party apps, in effect, were untrusted regardless of cert and therefore received the same SELinux domain. This also had the unfortunate side effect of forcing certain third party apps into the wrong domains because of shared userid requests among apps.

This patch removes that restriction and instead allows all apps, regardless of location, to be matched against the full mac_permissions.xml policy file. This then allows all apps signed with known good certs to receive the same SELinux domains of other apps with whom they share trust.

Some of this section has been extracted from the external/sepolicy/README file that should be checked in case there have been updates. It describes how files in external/sepolicy can be manipulated during the build process to reflect requirements of different device vendors whose policy files would normally be located in the device/<vendor>/<device>/sepolicy directory.

Additional per device policy files may be added or removed during the policy build and are configured through the use of the following four variables that would be added to the device BoardConfig.mk file:

BOARD_SEPOLICY_DIRS

BOARD_SEPOLICY_UNION

BOARD_SEPOLICY_REPLACE

BOARD_SEPOLICY_IGNORE

They are used as follows:

BOARD_SEPOLICY_DIRS

BOARD_SEPOLICY_DIRS contains a list of directories to search for files listed by the BOARD_SEPOLICY_UNION and BOARD_SEPOLICY_REPLACE variables. Order matters in this list. e.g. If the following is defined:

BOARD_SEPOLICY_UNION := widget.te

and there are two instances of widget.te files on the BOARD_SEPOLICY_DIRS search path, the first one found (at the first search directory containing the file) gets processed first. Reviewing the devices policy.conf[1] will help sort out ordering issues and is located at:

BOARD_SEPOLICY_UNION is a list of files that will be "unioned", i.e. concatenated at the END of their respective files in external/sepolicy

Note to add a unique/new file this variable would be used.

BOARD_SEPOLICY_REPLACE

BOARD_SEPOLICY_REPLACE is a list of files that will be used instead of the corresponding file in external/sepolicy.

BOARD_SEPOLICY_IGNORE

BOARD_SEPOLICY_IGNORE is a list of paths (directory + filename) of files that are not to be included in the resulting policy. This list is passed to filter-out to remove any paths to be ignored. This is useful if there are numerous configuration directories that contain a file, and that file is NOT to be included in the resulting policy, either by BOARD_SEPOLICY_UNION or BOARD_SEPOLICY_REPLACE.

with directories X and Y containing a copy of file A. The resulting policy is created by using Y/A only, thus X/A was ignored.

Error Handling:

It is an error to specify a BOARD_POLICY_REPLACE file that does not exist in external/sepolicy.

It is an error to specify a BOARD_POLICY_REPLACE file that appears multiple times on the policy search path defined by BOARD_SEPOLICY_DIRS.

For example, if shell.te is specified in BOARD_SEPOLICY_REPLACE and BOARD_SEPOLICY_DIRS is set to:

vendor/widget/common/sepolicy device/widget/x/sepolicy

and shell.te appears in both locations, it is an error. Unless it is in BOARD_SEPOLICY_IGNORE to be filtered out. See BOARD_SEPOLICY_IGNORE for more details.

It is an error to specify the same file name in both BOARD_POLICY_REPLACE and BOARD_POLICY_UNION.

It is an error to specify a BOARD_SEPOLICY_DIRS that has no entries when specifying BOARD_SEPOLICY_REPLACE.

Examples:
Two example BoardConfig.mk entries showing the use of BOARD_SEPOLICY_UNION that will take files referenced in BOARD_SEPOLICY_DIRS and add their contents to the end of the respective files in external/sepolicy, it will also include those not in external/sepolicy, and BOARD_SEPOLICY_REPLACE that will replace those files in external/sepolicy.

The kernel policy is compiled using checkpolicy(8) via the external/sepolicy/Android.mk file. There are also a number of SE for Android specific tools used to assist in policy configuration that are described in the Policy Build Tools section, with a summary as follows:

checkfc - Used to parse the file_contexts file against the binary policy sepolicy. This is to ensure all file contexts are valid for the policy. There is a -p option that is used to validate the contexts defined in the property_contexts or service_contexts file.

checkseapp - Used to validate the seapp_contexts file entries against the binary policy sepolicy.

insertkeys.py - Used to replace keywords in the signature sections of the mac_permissions.xml file with information obtained from pem files. This uses information contained in the external/sepolicy/keys.conf file that is detailed in the insertkeys.py tools section.

Note that the tools listed below are not built as part of the standard build process, therefore use make <tool_name> except where indicated.

post_process_mac_perms - Assists in generating new entries in an existing mac_permissions.xml file (also see setool). There is no make target for this python script, so either move to HOST_EXECUTABLE or execute directly (e.g. $PREFIX/external/sepolicy/tools/post_process_mac_perms).

sepolicy-analyze - Used to analyze the kernel policy file (sepolicy) for equivalent or different type pairs, or duplicate allow rules.

sepolicy-check - Used to check the kernel policy file (sepolicy) for allow rules based on source / target types, class and a single permission.

build<???>bundle - Used to build bundles for sepolicy et al., eop.xml or ifw.xml files to handle policy updates. Not available on AOSP.

setool - Assists in generating new entries for the mac_permissions.xml file. It will extract certificates from one or more packages then generate the package sections. Its output may need to be modified before inclusion in the master file as detailed in the setool tools section. Not available on AOSP.

Version 4.4 is always started in enforcing mode, although some domains may be running in 'per-domain' permissive mode due to the permissivestatement being present in the policy. Also in 4.4 there is a permissive_or_unconfined macro (see te_macros policy file) that can be controlled via the FORCE_PERMISSIVE_TO_UNCONFINED flag defined in the policy Android.mk file (see comments in Android.mk for the detail).

These are ways to set permissive or enforcing mode:

To set across reboots, add the setenforce command to init.rc or init.<board>.rc files.

Checks on file labels take place at boot time, policy upgrades / reloads, app installation / upgrade, and via adb using restorecon/chcon. Depending on whether data, app or system areas are being labeled by the various restorecon services, there are two files involved: file_contexts for all areas other than /data/data and /data/user where the seapp_contexts file is used. There use and format are decribed in the Policy Configuration Files and seapp_contexts File sections.

To determine whether either of these two files have changed:

The file_contexts file has an SHA hash taken when loaded. This will be used when a recursive restorecon request is made and will be written to the pathname inode xattr entry of "security.resorecon_last" as files are labeled (except /sys files). When restorecon is run again (policy reload/update etc.), the xattr hash will be compared to the loaded file_contexts file hash, thus allowing automatic relabeling should the file change.

The seapp_contexts file has an SHA hash taken when loaded and stored as /data/system/seapp_hash by SELinuxMMAC.java. This is used to determine whether a recursive restorecon should be carried out on the /data/data and data/user directories by the package manager.

As the requirement of the app is to only accept packets labeled net_apps_packet via iptables(8) SECMARK, the relabelto allow rule was added to the device policy (see the selinux-network.sh Configuration section for using SECMARK).

Note that before the auditing daemon is loaded messages will be logged in the kernel buffers that can be read using dmesg(1):