NB SEforAndroid 2

From SELinux Wiki
Revision as of 15:28, 16 April 2013 by RichardHaines (Talk | contribs)

Jump to: navigation, search

Policy File Configuration Details

This section details the specific SE for Android policy configuration files (i.e. those not used by 'standard' Linux based SELinux) as they were in April '13. Where those files are used to compute contexts using the SE for Android libselinux functions, those functions are also described with examples.

As this project is continually being enhanced, it is recommended that the official project wiki is checked for the latest enhancements at SEforAndroid


SELinux MAC Files

seapp_contexts File

This file is loaded and sorted into memory automatically on first use of one of the following SE for Android libselinux functions that are called by the SE for Android enabled services:

selinux_android_setcontext - Computes process security contexts.
selinux_android_setfilecon2 - Computes file/directory security contexts.

selinux_android_seapp_context_reload will also reload this file.

The build process supports additional seapp_contexts files to allow devices to specify their specific entries as described in the Building the Policy section.

The following sections will show:

  1. The default external/sepolicy/seapp_contexts file entries.
  2. A description of the seapp_contexts entries and their usage.
  3. A brief description of how a context is computed using either the selinux_android_setcontext or selinux_android_ setfilecon2 function using the seapp_contexts file entries.
  4. Examples of computed domain and directory contexts for various apps.

Default Entries

The default external/sepolicy/seapp_contexts file contains the following entries:

isSystemServer=true domain=system
user=system domain=system_app type=system_data_file
user=bluetooth domain=bluetooth type=bluetooth_data_file
user=nfc domain=nfc type=nfc_data_file
user=radio domain=radio type=radio_data_file
user=_app domain=untrusted_app type=app_data_file levelFrom=app
user=_app seinfo=platform domain=platform_app type=platform_app_data_file
user=_app seinfo=shared domain=shared_app type=platform_app_data_file
user=_app seinfo=media domain=media_app type=platform_app_data_file
user=_app seinfo=release domain=release_app type=platform_app_data_file
user=_isolated domain=isolated_app

Entry Definitions

The following has been extracted from the default file with some additional comments that describe the parameters and how they are used to compute a context:

Input selectors from seapp_contexts file:

isSystemServer (boolean)
user (string)
seinfo (string)
name (string) - A package name e.g. com.example.demo
sebool (string) - The boolean must be ‘active’ (enabled/true)

isSystemServer=true can only be used once. An unspecified isSystemServer defaults to false.

An unspecified string selector will match any value.

A user string selector that ends in * will perform a prefix match.

user=_app will match any regular app UID.

user=_isolated will match any isolated service UID.

All specified input selectors in an entry must match (i.e. logical AND).

Matching is case-insensitive.

Precedence rules:

1) isSystemServer=true before isSystemServer=false.
2) Specified user= string before unspecified user= string.
3) Fixed user= string before user= prefix (i.e. ending in *).
4) Longer user= prefix before shorter user= prefix.
5) Specified seinfo= string before unspecified seinfo= string.
6) Specified name= string before unspecified name= string.
7) Specified sebool= string before unspecified sebool= string.

Outputs:

domain (string) - The type component of a process context.
type (string) - The type component of a file/directory context.
levelFrom (string; one of none, all, app, or user) - A level that will be automatically computed based on the parameter.
level (string) - A predefined level (e.g. s0:c1022.c1023)

Only entries that specify domain= will be used for app process labeling. Only entries that specify type= will be used for app directory labeling. levelFrom=user is only supported for _app or _isolated UIDs. levelFrom=app or levelFrom=all is only supported for _app UIDs. level may be used to specify a fixed level for any UID.

Computing a Process Context

To compute an app process context the selinux_android_setcontext function is called that will use the parameters passed, plus the contents of the seapp_contexts file. The function parameters are:

#include <selinux/android.h>
int selinux_android_setcontext(uid_t uid, int isSystemServer, const char *seinfo, const char *pkgname);

The context is then computed using the information as follows:

The uid is converted to a string that is then used to match the user= entries in the seapp_contexts file as follows:
If an Android system service the uid is converted to a string via an internal Android table (e.g. "radio", "system").
If an isolated service the _isolated string is used.
For any other app or service the _app is used.
The isSystemServer value must match that set in the running system and be true or false. It will be matched against the isSystemServer= entries in the seapp_contexts file.
seinfo may be NULL or that obtained from the mac_permissions.xml file. It will be matched against the seinfo= entries in the seapp_contexts file.
pkgname may be NULL or that obtained from the Android package. It will be matched against the name= entries in the seapp_contexts file.
The remaining seapp_contexts entries will be used as follows:
The sebool= parameter if present will be matched against the SELinux boolean name list. If present, the boolean must be active.
The levelFrom= and level= parameters if present will be used to determine the level component of the security context.
The domain= is used to set the process context and must match a context in the policy. Determines the type component of the security context.

If a context is computed, it is validated against policy and if correct setcon(3) will then be used to set the process context.

Examples The following is an example taken as the system server is loaded:

Input selectors:
   uid             1000
   isSystemServer  true
   seinfo          null
   name            null
   sebool          null

username computed from uid = system

Matching seapp_contexts entry:
   isSystemServer=true domain=system

Outputs:
   domain system
   level s0

Computed context u:r:system:s0

Result using ps -Z command:
LABEL          USER   PID  PPID NAME
u:r:system:s0  system 300  45   system_server

This is the "radio" application that is part of the platform:

Input selectors:
   uid             1001
   isSystemServer  false
   seinfo          platform
   name            com.android.phone
   sebool          null
 
username computed from uid = radio

Matching seapp_contexts entry:
   user=radio domain=radio type=radio_data_file

Outputs:
   domain radio
   level s0

Computed context u:r:radio:s0

Result using ps -Z command:
LABEL         USER   PID  PPID  NAME
u:r:radio:s0  radio  443  45    com.android.phone

This is the "SE for Android Admin Manager" application that is part of the platform:

Input selectors:
   uid             10042
   isSystemServer  false
   seinfo          release
   name            com.android.seandroid_admin
   sebool          null

username computed from uid = u0_a42

Matching seapp_contexts entry:
   user=_app seinfo=release domain=release_app type=platform_app_data_file

Outputs:
   domain release_app
   level s0

Computed context u:r:release_app:s0

Result using ps -Z command:
LABEL               USER     PID   PPID   NAME
u:r:release_app:s0  u0_a42   827   45     com.android.seandroid_admin

This is a third party app that also runs an isolated service:

Input selectors:
   uid             10046
   isSystemServer  false
   seinfo          null
   name            com.example.seandroiddemo
   sebool          null

username computed from uid = u0_a46

Matching seapp_contexts entry:
   user=_app domain=untrusted_app type=app_data_file levelFrom=app

Outputs:
   domain untrusted_app
   levelFrom app s0:c46,c256

Computed context u:r:untrusted_app:s0:c46,c256

Result using ps -Z command:
LABEL                           USER     PID   PPID  NAME
u:r:untrusted_app:s0:c46,c256   u0_a46   855   45    com.example.seandroiddemo
Input selectors:
   uid             99000
   isSystemServer  false
   seinfo          null
   name            com.example.seandroiddemo
   sebool          null
 
username computed from uid = u0_i0

Matching seapp_contexts entry:
   user=_isolated domain=isolated_app

Outputs:
   domain isolated_app
   level s0

Computed context u:r:isolated_app:s0

Result using ps -Z command:
LABEL                 USER    PID   PPID  NAME
u:r:isolated_app:s0   u0_i0   869   45    com.example.seandroiddemo

Computing a Directory Context

To compute an app package directory context the selinux_android_setfilecon2 function is called that will use the parameters passed, plus the contents of the seapp_contexts file. The function parameters are:

#include <selinux/android.h>

int selinux_android_setfilecon2(const char *pkgdir, const char *pkgname, const char *seinfo, uid_t uid);

The context is then computed using the information as follows:

pkgdir is the file or directory to be labeled with the computed context.
pkgname may be NULL or that obtained from the Android package. It will be matched against the name= entries in the seapp_contexts file.
seinfo may be NULL or that obtained from the mac_permissions.xml file. It will be matched against the seinfo= entries in the seapp_contexts file.
The uid is converted to a string that is then used to match the user= entries in the seapp_contexts file as follows:
If an Android system service the uid is converted to a string via an internal Android table (e.g. "radio", "system").
If an isolated service the _isolated string is used.
For any other app or service the _app is used.
The remaining seapp_contexts entries will be used as follows:
The sebool= parameter if present will be matched against the SELinux boolean name list. If present, the boolean must be active.
The levelFrom= and level= parameters if present will be used to determine the level component of the security context.
The type= is used to set the file object context and must match a context in the policy. Determines the type component of the security context.

If a context is computed, it is validated against policy and if correct setfilecon(3) will then be used to label pkgdir with the computed context. The following example is from a third party app:

Input selectors:
   uid             10046
   isSystemServer  false
   seinfo          null
   name            com.example.seandroiddemo
   sebool          null
   pkgdir          /data/data/com.example.seandroiddemo

username computed from uid = u0_a46

Matching seapp_contexts entry:
   user=_app domain=untrusted_app type=app_data_file levelFrom=app

Outputs:
   type           app_data_file
   levelFrom app  s0:c46,c256

Computed context u:object_r:app_data_file:s0:c46,c256

Result from /data/data directory using ls -Z command:
drwxr-x--x u0_a46 u0_a46 u:object_r:app_data_file:s0:c46,c256 com.example.seandroiddemo

Example ls -Z /data/data entries:

drwxr-x--x u0_a35 u0_a35 u:object_r:platform_app_data_file:s0 com.android.backupconfirm
drwxr-x--x bluetooth bluetooth   u:object_r:bluetooth_data_file:s0 com.android.bluetooth
drwxr-x--x u0_a7    u0_a7        u:object_r:platform_app_data_file:s0 com.android.browser
drwxr-x--x u0_a37   u0_a37       u:object_r:platform_app_data_file:s0 com.android.deskclock
drwxr-x--x u0_a21   u0_a21       u:object_r:platform_app_data_file:s0 com.android.development
drwxr-x--x u0_a30   u0_a30       u:object_r:platform_app_data_file:s0 com.android.mms
drwxr-x--x u0_a19   u0_a19       u:object_r:platform_app_data_file:s0 com.android.music
drwxr-x--x u0_a31   u0_a31       u:object_r:platform_app_data_file:s0 com.android.musicfx
drwxr-x--x u0_a5    u0_a5        u:object_r:platform_app_data_file:s0 com.android.musicvis
drwxr-x--x u0_a17   u0_a17       u:object_r:platform_app_data_file:s0 com.android.noisefield
drwxr-x--x system   system       u:object_r:system_data_file:s0 com.android.providers.settings
drwxr-x--x radio    radio        u:object_r:radio_data_file:s0 com.android.providers.telephony
drwxr-x--x u0_a0    u0_a0        u:object_r:platform_app_data_file:s0 com.android.provision
drwxr-x--x u0_a34   u0_a34       u:object_r:platform_app_data_file:s0 com.android.quicksearchbox
drwxr-x--x u0_a42   u0_a42       u:object_r:platform_app_data_file:s0 com.android.seandroid_admin
drwxr-x--x system   system       u:object_r:system_data_file:s0 com.android.settings
drwxr-x--x u0_a14   u0_a14       u:object_r:platform_app_data_file:s0 com.android.smspush
drwxr-x--x u0_a26   u0_a26       u:object_r:platform_app_data_file:s0 com.android.soundrecorder
drwxr-x--x u0_a2    u0_a2        u:object_r:platform_app_data_file:s0 com.android.speechrecorder
drwxr-x--x u0_a4    u0_a4        u:object_r:platform_app_data_file:s0 com.android.systemui
drwxr-x--x u0_a11   u0_a11       u:object_r:platform_app_data_file:s0 com.android.videoeditor
drwxr-x--x u0_a12   u0_a12       u:object_r:platform_app_data_file:s0 com.android.voicedialer
drwxr-x--x u0_a10   u0_a10       u:object_r:platform_app_data_file:s0 com.android.vpndialogs
drwxr-x--x u0_a16   u0_a16       u:object_r:platform_app_data_file:s0 com.android.wallpaper
drwxr-x--x u0_a46   u0_a46       u:object_r:app_data_file:s0:c46,c256 com.example.seandroiddemo


property_contexts File

This file holds property names and their contexts that will be applied by SELinux when applications are loaded. The property names reflect the 'white list' of Android property entries that are also built into the system (see system/core/init/property_service.c and init.c) however there are also additional property entries for applications that require specific contexts to be set. The build process supports additional seapp_contexts files to allow devices to specify their specific entries as described in the Building the Policy section. When selabel_open(3) is called specifying this file it will be read into memory and sorted using qsort(3), subsequent calls using selabel_lookup(3) will then retrieve the appropriate context. Each line within the property contexts file is as follows:

property_key context

Where:

property_key
The key used to obtain the context that may contain '*' for wildcard matching.
context
The security context that will be applied to the object.

The default property_contexts file entries are:

##########################
# property service keys
#
 
net.rmnet0              u:object_r:radio_prop:s0
net.gprs                u:object_r:radio_prop:s0
net.ppp                 u:object_r:radio_prop:s0
net.qmi                 u:object_r:radio_prop:s0
net.lte                 u:object_r:radio_prop:s0
net.cdma                u:object_r:radio_prop:s0
gsm.                    u:object_r:radio_prop:s0
persist.radio           u:object_r:radio_prop:s0
net.dns                 u:object_r:radio_prop:s0
sys.usb.config          u:object_r:radio_prop:s0
ril.                    u:object_r:rild_prop:s0
net.                    u:object_r:system_prop:s0
dev.                    u:object_r:system_prop:s0
runtime.                u:object_r:system_prop:s0
hw.                     u:object_r:system_prop:s0
sys.                    u:object_r:system_prop:s0
service.                u:object_r:system_prop:s0
wlan.                   u:object_r:system_prop:s0
dhcp.                   u:object_r:system_prop:s0
debug.                  u:object_r:shell_prop:s0
log.                    u:object_r:shell_prop:s0
service.adb.root        u:object_r:shell_prop:s0
service.adb.tcp.port    u:object_r:shell_prop:s0

persist.audio.          u:object_r:audio_prop:s0
persist.sys.            u:object_r:system_prop:s0
persist.service.        u:object_r:system_prop:s0
persist.security.       u:object_r:system_prop:s0

# mmac persistent properties
persist.mmac.u:object_r:security_prop:s0

# selinux non-persistent properties
selinux.                u:object_r:security_prop:s0
 
# default property context
*                      u:object_r:default_prop:s0

# data partition encryption properties
vold.                   u:object_r:vold_prop:s0
crypto.                 u:object_r:vold_prop:s0

# ctl properties
ctl.dumpstate           u:object_r:ctl_dumpstate_prop:s0
ctl.ril-daemon          u:object_r:ctl_rildaemon_prop:s0
ctl. 							u:object_r:ctl_default_prop:s0


Install MMAC File

The mac_permissions.xml file is used to configure install-time MMAC policy and provides two main functions:

  1. x.509 certificate to seinfo string mapping so that Zygote spawns the application in the correct domain. See the Computing a Process Context section for how this is achieved using information also contained in the seapp_contexts file.
  2. Install-time MMAC permission checking.

It is important to note that all third party apps will be subject to the <default> install MAC policy defined in this file. This is a requirement of AOSP in that all third party apps must be treated alike (i.e. distinctions can only be made between system apps and third party apps and among the system apps, not between two different third party apps). The current <default> package policy is as follows:

<!-- All other keys -->
<default>
    <seinfo value="default" /></nowiki>
    <deny-permission name="android.permission.ACCESS_COARSE_LOCATION" />
    <deny-permission name="android.permission.ACCESS_FINE_LOCATION" />
    <deny-permission name="android.permission.AUTHENTICATE_ACCOUNTS" />
    <deny-permission name="android.permission.CALL_PHONE" />
    <deny-permission name="android.permission.CAMERA" />
    <deny-permission name="android.permission.READ_LOGS" />
    <deny-permission name="android.permission.WRITE_EXTERNAL_STORAGE" />
</default>>

The build process supports additional mac_permissions.xml files to allow devices to specify their specific entries as described in the Building the Policy section.

Signature Entries

The <signer signature= entry may have the public base16 signing key present in the string or it may have an entry starting with @, then a keyword as shown that allows the key to be extracted from a pem file as discussed in the insertkeys.py section:

    <!-- Platform dev key in AOSP -->
    <signer signature="@PLATFORM" >
        <allow-all />
        <seinfo value="platform" />
    </signer>

If a base16 key is required, it can be extracted from a package using the setool utility as described in the setool section.

Policy Rules

The following rules have been extracted from the source mac_permissions.xml file:

  • A signature is a hex encoded X.509 certificate and is required for each signer tag.
  • A <signer signature="" > element may have multiple child elements:
    • allow-permission : produces a set of maximal allowed permissions (whitelist).
    • deny-permission : produces a blacklist of permissions to deny.
    • allow-all : a wildcard tag that will allow every permission requested.
    • package : a complex tag which itself defines allow, deny, and wildcard sub elements for a specific package name protected by the signature.
  • Zero or more global <package name=""> tags are allowed. These tags allow a policy to be set outside any signature for specific package names.
  • Unknown tags at any level are skipped.
  • Zero or more signer tags are allowed.
  • Zero or more package tags are allowed per signer tag.
  • A <package name=""> tag may not contain another <package name=""> tag. If found, it's skipped.
  • A <default> tag is allowed that can contain install policy for all apps not signed with a previously listed cert and not having a per package global policy.
  • When multiple sub elements appear for a tag the following logic is used to ultimately determine the type of enforcement:
    • A blacklist is used if at least one deny-permission tag is found
    • A whitelist is used if not a blacklist and at least one allow-permission tag is found
    • A wildcard (accept all permission) policy is used if not a blacklist and not a whitelist and at least one allow-all tag is present.
    • If a <package name=""> sub element is found then that sub element's policy is used according to the above logic and overrides any signature global policy type.
    • In order for a policy stanza to be enforced at least one of the above situations must apply. Meaning, empty signer, default or package tags will not be accepted.
  • Each signer / default / global package tag is allowed to contain one <seinfo value=""/> tag. This tag represents additional information that each application can use in setting a SELinux security context on the eventual process. Any <seinfo value=""/> tag found as a child of a <package name=""> tag which is protected (sub element of signer or the default tag) is ignored. It's possible that multiple seinfo tags are relevant for one application. In the event that this happens, the seinfo tag that will be applied is the one for which the corresponding policy stanza is used in the policy decision.
  • Strict enforcing of any xml stanza is not enforced in most cases. This mainly applies to duplicate tags which are allowed. In the event that a tag already exists, the original tag is replaced.
  • There are also no checks on the validity of permission names. Although valid android permissions are expected, nothing prevents unknowns.
  • Enforcement decisions:
    • All signatures used to sign an application are checked for policy according to signer tags. Only one of the signature policies has to pass however.
    • In the event that none of the signature policies pass, or none even match, then a global package policy is sought. If found, this policy mediates the install.
    • The default tag is consulted last if needed.
    • A local package policy always overrides any parent policy.
    • If none of the cases apply then the app is denied.

An edited form of the default mac_permissions.xml file is as follows:

<?xml version="1.0" encoding="utf-8"?>
<policy>
    <!-- Platform dev key in AOSP -->
    <signer signature="@PLATFORM" >
        <allow-all />
        <seinfo value="platform" />
    </signer>

    <!-- Media dev key in AOSP -->
    <signer signature="@MEDIA" >
        <allow-permission name="android.permission.ACCESS_ALL_DOWNLOADS" />
        <allow-permission name="android.permission.WRITE_EXTERNAL_STORAGE" />
        <allow-permission name="android.permission.WRITE_MEDIA_STORAGE" />
        <allow-permission name="android.permission.WRITE_SETTINGS" />
        <seinfo value="media" />
    </signer>

    <!-- shared dev key in AOSP -->
    <signer signature="@SHARED" >
        <allow-permission name="android.permission.ACCESS_COARSE_LOCATION" />
        <allow-permission name="com.android.voicemail.permission.ADD_VOICEMAIL" />
        <seinfo value="shared" />
    </signer>

    <!-- release dev key in AOSP -->
    <signer signature="@RELEASE" >
        <seinfo value="release" />
        <deny-permission name="android.permission.BRICK" />
        <deny-permission name="android.permission.READ_LOGS" />
        <package name="com.android.browser" >
          <allow-permission name="android.permission.SET_WALLPAPER" />
          <allow-permission name="android.permission.USE_CREDENTIALS"/>
          <allow-permission name="android.permission.WAKE_LOCK"/>
          <allow-permission name="android.permission.WRITE_EXTERNAL_STORAGE" />
          <allow-permission name="android.permission.WRITE_SETTINGS" />
          <allow-permission name="android.permission.WRITE_SYNC_SETTINGS" />
          <seinfo value="release" />
        </package>
    </signer>

    <!-- All other keys -->
    <default>
        <seinfo value="default" />
        <deny-permission name="android.permission.ACCESS_COARSE_LOCATION" />
        <deny-permission name="android.permission.ACCESS_FINE_LOCATION" />
        <deny-permission name="android.permission.AUTHENTICATE_ACCOUNTS" />
        <deny-permission name="android.permission.CALL_PHONE" />
        <deny-permission name="android.permission.CAMERA" />
        <deny-permission name="android.permission.READ_LOGS" />
        <deny-permission name="android.permission.WRITE_EXTERNAL_STORAGE" />
    </default>
</policy>


Intent MAC Files

There are two configuration files to support intent MAC, they are:

intent_mac.xml - This defines the intents that will be allowed between each source and destination. The source and destination may be package names or <type> entries defined in the mmac_types.xml file that will allow intents to be managed on a package, signature and/or permissions basis. There is also an optional <allow-all> section.
mmac_types.xml - Contains <type> entries allowing source and destination entries defined in the intent_mac.xml file to manage intents on a package, signature and/or permissions basis.

intent_mac.xml File

The file supports two entry types:

  1. An intent filter that specifies actions (intents) and the types (defined in mmac_types.xml) that can be either the source or destination of the action.
  2. An <allow-all> entry.

Currently the build process does not support multiple intent_mac.xml files, however this will probably change.

Intent Filter Entry

The entries are defined below with:

  • The <action name="" /> entry will define the intent.
  • The src= and dst= entries may be package names or 'type names' that are further defined in the mmac_types.xml file.
  • The srcctx= entry if defined will be matched against the app process source context.
<?xml version="1.0" encoding="utf-8"?>
<policy>                           <!-- Start intent_mac.xml entries -->

    <intent>                       <!-- Starts a new intent filter -->
        <filter>
            <action name="" />     <!-- Only one entry allowed-->
        <!-- or-->
            <category name="" />   <!-- Multiple entries allowed -->
    </filter>
    <allow                         <!-- Multiple entries allowed -->
        name=""                    <!-- Rule name -->
        srcctx=""                  <!-- Source context to be matched -->
        src=""                     <!-- Source <type> entry or package name -->
        dst=""                     <!-- Destination <type> entry or package name -->
    </allow>
    </intent>

</policy>                          <!-- End entries -->

An example entry is:

<?xml version="1.0" encoding="utf-8"?>

<policy>
    <intent>
        <filter>
            <action name="android.bluetooth.adapter.action.LOCAL_NAME_CHANGED"/>
        </filter>
        <allow src="bluetooth" dst="settings"/>
        <allow src="bluetooth" dst="android"/>
        <allow src="bluetooth" dst="settings"/>
    </intent>
</policy>

Allow-all Entry

The entries are defined below with:

  • The src= and dst= entries are generally package names as all intents will be allowed, however they may be 'type names' that are further defined in the mmac_types.xml file.
  • The srcctx= entry if defined will be matched against the app process source context.
<?xml version="1.0" encoding="utf-8"?>
<policy>                    <!-- Start intent_mac.xml entries -->

    <allow-all>             <!-- Starts a new intent filter -->
        <allow              <!-- Multiple entries allowed -->
          name=""           <!--</nowiki></tt> Rule name -->
          srcctx=""         <!-- Source context to be matched -->
          <tt>src=""        <!-- Source <type> entry or package name -->
          <tt>dst=""        <!-- Destination <type> entry or package name -->
        </allow>
    </allow-all>
</policy>                   <!-- End entries -->

An <allow-all> example entry:

<?xml version="1.0" encoding="utf-8"?>
<policy>

    <allow-all>
        <allow name="phone_to_sms" src="com.android.phone" dst="com.android.smspush"/>
        <allow name="shell" srcctx="u:r:shell:s0"/>
        <allow name="su" srcctx="u:r:su:s0"/>
    </allow-all>

</policy>


mmac_types.xml File

The build process supports additional mmac_types.xml files to allow devices to specify their specific entries as described in the [#2.10.5.Building the Policy|outline Building the Policy] section that will also expand any signatures.

The entries are defined below with:

  • The <type name="" /> entry defines the 'type name' entry that will be referenced by the intent_mac.xml file src="" and dst="" entries. The entry will define signatures, package names and or permissions.
  • The <signature value="" /> entries may be the key as extracted by setool (but it will need to be copied from the output produced by setool), or use the "@.." show in the example below, this will then be generated as a part of the build process by insertkeys.py.
  • The srcctx= entry if defined will be matched against the app process source context.
<?xml version="1.0" encoding="utf-8"?>
<types>                         <!--Start entries -->

   <type name="" />             <!-- The type entries 'name' -->
     <signature value="" />     <!-- Multiple entries allowed -->
     <package value="" />       <!-- Multiple entries allowed -->
     <permission value="" />    <!-- Rule name -->
    </type>

</types>                         <!-- End entries -->

Example entries are:

<?xml version="1.0" encoding="utf-8"?>
<types>
    <type name="telephony_app">
        <signature value="@PLATFORM"/>
        <package value="com.android.phone"/>
    </type>

    <type name="video_perm">
        <permission value="android.permission.CAMERA"/>
        <permission value="android.permission.RECORD_AUDIO"/>
    </type>
</types>


Revoke Permissions File

The revoke_permissions.xml file is used to configure revoked permissions. The build process does not currently support additional files. The revoke_permissions.xml file entries are as follows:

<?xml version="1.0" encoding="utf-8"?>
<revoke-policy>                 <!-- Start entries -->

    <package name="" />         <!-- Package containing permissions to revoke -->
     <revoke-permission="" />   <!-- Multiple entries allowed -->
    </package>

 <revoke-policy>                <!-- End entries -->

Example entries are:

<?xml version="1.0" encoding="utf-8"?></nowiki>
<revoke-policy></nowiki>

    <package name="com.example.seandroiddemo">
        <revoke-permission name="com.example.seandroiddemo.permission.DEADLY_ACTIVITY"/>
    </package><

    <package name="com.example.seandroiddemob">
        <revoke-permission name="android.permission.CAMERA"/>
    </package>

</revoke-policy>


Policy Build Tools

This section covers the policy build tools located at external/sepolicy/tools. They are checkfc, checkseapp and insertkeys.py. There is also setool that is not used as part of the build process but generates mac_permissions.xml entries from packages.

checkfc

The checkfc utility is used during the build process to validate the file_contexts and property_contexts files against policy. If validation fails checkfc will exit with an error.

checkfc -h will give the following output:

usage: checkfc [OPTIONS] sepolicy context_file
Parses a context file and checks for syntax errors.
The context_file is assumed to be a file_contexts file
unless explicitly switched by an option.

    OPTIONS:
        -p : context file represents a property_context file.

Example validating file_contexts file:

checkfc out/target/product/generic/root/sepolicy out/target/product/generic/root/file_contexts

Example validating property_contexts file:

checkfc -p out/target/product/generic/root/sepolicy out/target/product/generic/root/property_contexts

checkseapp

The checkseapp utility is used during the build process to validate the seapp_contexts file against policy. If validation fails checkseapp will exit with an error. checkseapp also consolidates matching entries and outputs the valid file stripped of comments.

checkseapp -h will give the following output:

checkseapp [options] <input file>
Processes an seapp_contexts file specified by argument <input file> (default stdin) and allows later declarations to 
override previous ones on a match.
Options:
    -h - print this help message
    -v - enable verbose debugging informations
    -p policy file - specify policy file for strict checking of output selectors
    -o output file - specify output file, default is stdout

An example command with output to stdout is:

checkseapp -p out/target/product/generic/root/sepolicy out/target/product/generic/root/seapp_contexts
isSystemServer=true domain=system
user=system domain=system_app type=system_data_file
user=bluetooth domain=bluetooth type=bluetooth_data_file
user=nfc domain=nfc type=nfc_data_file
user=radio domain=radio type=radio_data_file
user=_app domain=untrusted_app type=app_data_file levelFrom=app
user=_app seinfo=platform domain=platform_app type=platform_app_data_file
user=_app seinfo=shared domain=shared_app type=platform_app_data_file
user=_app seinfo=media domain=media_app type=platform_app_data_file
user=_app seinfo=release domain=release_app type=platform_app_data_file
user=_isolated domain=isolated_app

insertkeys.py

The insertkeys.py utility is used during the build process to insert signing keys into multiple mac_permissions.xml and mmac_types.xml files. The keys are obtained from pem files and the entries to be replaced start with an @ followed by a keyword. The external/sepolicy/keys.conf file contains corresponding entries that allow mapping of pem files to signatures as discussed in the keys.conf section.

Note that pem files are base64 encoded however the Android Package Manager Service uses base16 encodings. Therefore insertkeys.py and setool will generate base16 encodings for the mac_permissions.xml and mmac_types.xml files.

insertkeys.py will also strip the files of comments and whitespace to preserve space on the system.img. To view the output file in a more human friendly format the tidy or xmllint command can be used.

insertkeys.py -h will give the following output:

Usage: insertkeys.py [options] CONFIG_FILE MAC_PERMISSIONS_FILE [MAC_PERMISSIONS_FILE...]

This tool allows one to configure an automatic inclusion of signing keys into the mac_permission.xml file(s) from the pem files. 
If multiple mac_permission.xml files are included then they are unioned to produce a final version.

Options:
    --version show program's version number and exit
    -h, --help show this help message and exit
    -v, --verbose Print internal operations to stdout
    -o FILE, --output=FILE Specify an output file, default is stdout
    -c DIR, --cwd=DIR Specify a root (CWD) directory to run this from, itchdirs' AFTER loading the config file
    -t TARGET_BUILD_VARIANT, --target-build-variant=TARGET_BUILD_VARIANT
       Specify the TARGET_BUILD_VARIANT, defaults to eng

An example command that takes two mac_permission.xml files inserts the signatures and concatenates them into a single file is:

insertkeys.py -o demo/unioned_mac_permissions.xml external/sepolicy/keys.conf \
external/sepolicy/mac_permissions.xml demo/mac_permissions.xml

keys.conf

The keys.conf file is used by insertkeys.py for mapping the "@..." tags in mac_permissions.xml and mmac_types.xml signature entries with public keys found in pem files. The configuration file can be used in BOARD_SEPOLICY_UNION and BOARD_SEPOLICY_REPLACE variables and is processed via m4 macros.

insertkeys.py allows for mapping any string contained in TARGET_BUILD_VARIANT with a specific path to a pem file. Typically TARGET_BUILD_VARIANT is either user, eng or userdebug. Additionally "ALL" may be specified to map a path to any string specified in TARGET_BUILD_VARIANT. All tags are matched verbatim and all options are matched lowercase. The options are "tolowered" automatically for the user, it is convention to specify tags and options in all uppercase and tags start with @.

An example keys.conf file is as follows:

#
# Maps an arbitrary tag [TAGNAME] with the string contents found in
# TARGET_BUILD_VARAINT. Common convention is to start TAGNAME with an @ and
# name it after the base file name of the pem file.
#
# Each tag (section) then allows one to specify any string found in
# TARGET_BUILD_VARIANT. Typically this is user, eng, and userdebug. Another
# option is to use ALL which will match ANY TARGET_BUILD_VARAINT string.
#

[@PLATFORM]
ALL : build/target/product/security/platform.x509.pem

[@MEDIA]
ALL : build/target/product/security/media.x509.pem

[@SHARED]
ALL : build/target/product/security/shared.x509.pem

# Example of ALL TARGET_BUILD_VARIANTS
[@RELEASE]
ENG : build/target/product/security/testkey.x509.pem
USER : build/target/product/security/testkey.x509.pem
USERDEBUG : build/target/product/security/testkey.x509.pem

setool

The setool utility is not used during the build process and is intended only to produce 'starter' entries for the mac_permissions.xml file.

The entries produced will generally have to be modified because currently:

  1. If multiple packages are given each with the same signature, a separate entry will be generated for each package. If added to the mac_permissions.xml file only the first entry will be used by the Install-time MMAC process (therefore the packages need to be consolidated into on entry).
  2. setool will generate (--build) entries for third party apps, however it should not as they will be ignored by the install-time MMAC.
  3. setool will check (--policy) third party apps against the full mac_permissions.xml policy, however it should not, it should only check them against the <default> entries only.

Having said that, setool is still useful as it will generate the signature entries and extract the permissions.

setool --help will give the following output:

Usage: setool [flags] <--build|--policy> <apks>

Tool to help build and verify MMAC install policies.

apks List of apks to analyze, space separated. All supplied apks must
be absolute paths or relative to --apkdir (which defaults to the current directory).

--build Generate an MMAC style policy stanza. The resulting stanza can then be used as an entry in the mac_permissions.xml file.
    whitelist 
        Policy entry that contains a white listing of all permissions. The stanza will contain the app's package tag within its
        signer tag.
    keys 
        Print a valid signer tag which contains the hex encoded X.509 cert of the app.

--policy Determine if supplied apks pass the supplied policy.

Flags:
   --help Prints this message and exits.
   --apkdir Directory to search for supplied apks (default to current directory).
   --verbose Increase the amount of debug statements.
   --outfile Dump all output to the given file (defaults to stdout).
   --seinfo Create an seinfo tag for all generated policy stanzas.

The following are examples of using setool, however, note that they will not produce a valid policy for third party apps.

Assuming in Android project directory ($PREFIX) and there is a "demo" directory present, run setool to extract the package info and generate white list entries from a package (any package will suffice for the example):

setool --seinfo demo --build whitelist demo/SEAndroidDemo.apk > demo/ mac_permissions.xml

The output will be:

<signer signature="- key will be here -">
    <package name="com.example.seandroiddemo">
        <allow-permission name="android.permission.READ_EXTERNAL_STORAGE" />
        <allow-permission name="android.permission.SEND_SMS" />
        <allow-permission name="android.permission.WRITE_EXTERNAL_STORAGE" />
        <allow-permission name="com.example.seandroiddemo.permission.DEADLY_ACTIVITY" />
      <seinfo value="demo" />
    </package>
</signer>

Now assuming a emulator build, add an entry to the BoardConfig.mk file build/target/board/generic/BoardConfig.mk as follows:

BOARD_SEPOLICY_DIRS := \
        demo

BOARD_SEPOLICY_UNION := \
        mac_permissions.xml

Type make to rebuild policy changes and run setool to check the final concatenated mac_permissions.xml policy:

setool --policy out/target/product/generic/system/etc/security/mac_permissions.xml demo/SEAndroidDemo.apk

Policy passed for com.example.seandroiddemo (demo/SEAndroidDemo.apk).

uid To username Utility

This utility will take an Android uid and convert it to a username. The code is a modified version from bionic/libc/bionic/stubbs.cpp that converts an Android uid to username.

To compile this assumes that the environment variable $PREFIX is set to the Android project directory. This is to allow the header file to be located:

cc -std=gnu99 uid_to_username.c -o uid_to_username -include \
$PREFIX/system/core/include/private/android_filesystem_config.h
#include <stdio.h>
#include <stdlib.h>
#define CAT_MAPPING_MAX_ID (0x1<<16)

int main(int argc, char **argv)
{
    uid_t uid;

    if (argc != 2) {
        printf("Converts an Android uid to username\n");
        printf("usage: %s uid\n\n", argv[0]);
        exit(1);
    }
    uid = atoi(argv[1]);
    uid_t appid = uid % AID_USER;
    uid_t userid = uid / AID_USER;

    if (appid >= CAT_MAPPING_MAX_ID || userid >= CAT_MAPPING_MAX_ID) {
        printf("Failed as the maximum uid that can be mapped has been exceeded.\n");
        exit(0);
    }
    printf("appid: %u userid: %u\nusername: ", appid, userid);

    if (appid >= AID_ISOLATED_START) {
        printf("u%u_i%u\n", userid, appid - AID_ISOLATED_START);
    } else if (userid == 0 && appid >= AID_SHARED_GID_START) {
        printf("all_a%u\n", appid - AID_SHARED_GID_START);
    } else if (appid < AID_APP) {
        for (size_t n = 0; n < android_id_count; n++) {
            if (android_ids[n].aid == appid) {
                printf("u%u_%s\n", userid, android_ids[n].name);
                printf("Note that only the name \"%s\" is listed in 'ps' etc.\n", android_ids[n].name);
                exit(0);
            }
        }
        printf("Failed - invalid uid\n");
    } else {
        printf("u%u_a%u\n", userid, appid - AID_APP);
    }
    exit(0);
}