Privileged Permission Whitelisting

Privileged apps are system apps that are located in a priv-app directory on one of the system image partitions. The partitions used for Android releases are

  • Android 8.1 and lower - /system
  • Android 9 and higher - /system, /product, /vendor

Throughout this page, /etc/permissions/priv-app resolves to partition/etc/permissions/priv-app.

Historically, device manufacturers had little control over which signature|privileged permissions could be granted to privileged apps. Starting in Android 8.0, manufacturers must explicitly grant privileged permissions in the system configuration XML files in the /etc/permissions directory. As of Android 9, implementors must explicitly grant or deny all privileged permissions or the device won’t boot.

The privapp-permissions.xml file can only grant or deny permissions for privileged apps on the same partition. For example, if an app on the /vendor partition requests privileged permissions, the request can only be granted or denied by a privapp-permissions.xml file that’s also on /vendor.

Adding whitelists

Permission whitelists for apps can be listed in a single XML or in multiple XML files located in the frameworks/base/etc/permissions directory as follows:

  • /etc/permissions/privapp-permissions-OEM_NAME.xml
  • /etc/permissions/privapp-permissions-DEVICE_NAME.xml

There is no strict rule for organizing content. Device implementers can determine content structure as long as all apps from /system/priv-app are whitelisted. For example, Google has a single whitelist for all privileged apps developed by Google, and recommends the following organization:

  • Permissions for apps that are already included in the Android Open Source Project (AOSP) tree are listed in /etc/permissions/privapp-permissions-platform.xml.
  • Permissions for Google apps are listed in /etc/permissions/privapp-permissions-google.xml.
  • For other apps, use files of the form: /etc/permissions/privapp-permissions-DEVICE_NAME.xml.

Generating whitelists

To automatically generate a whitelist for all apps available on the system image, use the AOSP command line tool at development/tools/privapp_permissions/privapp_permissions.py. To generate an initial version of device-specific privapp-permissions.xml:

  1. Build a system image:
        . build/envsetup.sh
        lunch PRODUCT_NAME
        make -j
  2. Run the privapp_permissions.py script to generate a privapp-permissions.xmlfile that lists all signature|privileged permissions required to be whitelisted:
    development/tools/privapp_permissions/privapp_permissions.py
    This tool prints XML content that can be used either as a single file, or split into multiple files in the /etc/permissions directory path. If the device already includes whitelists in the /etc/permissions directories, the tool only prints the differences only (such as the missing signature|privileged permissions you need to add to the whitelist). This is also useful for audit purposes: When a new version of the app is added, the tool detects the additional permissions needed.
  3. Copy the generated files to the appropriate /etc/permissions directory, where the system reads the files during boot.

Customizing whitelists

AOSP includes a whitelist implementation that can be customized as needed. Permissions for apps included in AOSP are already whitelisted in /etc/permissions/privapp-permissions-platform.xml.

By default, the privapp_permissions.py script generates output that automatically grants any permission requested by a privileged application. If there are permissions that should be denied, edit the XML to use a "deny-permission" tag instead of a "permission" tag. Example:

<!--
    This XML file declares which signature|privileged permissions should be
    granted to privileged apps that come with the platform
    -->
    <permissions>
<privapp-permissions package="com.android.backupconfirm">
    <permission name="android.permission.BACKUP"/>
    <permission name="android.permission.CRYPT_KEEPER"/>
</privapp-permissions>
<privapp-permissions package="com.android.cellbroadcastreceiver">
    <!-- don't allow application to interact across users -->
    <deny-permission name="android.permission.INTERACT_ACROSS_USERS"/>
    <permission name="android.permission.MANAGE_USERS"/>
    <permission name="android.permission.MODIFY_PHONE_STATE"/>
    <permission name="android.permission.READ_PRIVILEGED_PHONE_STATE"/>
    <permission name="android.permission.RECEIVE_EMERGENCY_BROADCAST"/>
</privapp-permissions>
    ...

Finding missing permissions

To find missing permisisons when bringing up a new device, enable transitional log mode:

ro.control_privapp_permissions=log

Violations are reported in the log file, but nonprivileged permissions are still granted. This keeps the device in a working state while providing the list of violations. This is the error message format:

PackageManager: Privileged permission {PERMISSION_NAME} for package {PACKAGE_NAME} - not in privapp-permissions whitelist

All violations must be addressed by adding the missing permissions to the appropriate whitelists.

  • On Android 8.0 and lower, the affected apps aren’t granted the missing permissions even if they are in the priv-app path.
  • On Android 9 and higher, violations (of privileged permissions) mean the device doesn’t boot. You must explicitly either allow or deny all privileged permissions

Enforcing whitelists

After whitelists are in place, enable runtime enforcement by setting the build property ro.control_privapp_permissions=enforce.