特权应用是位于系统映像某个分区上 priv-app
目录下的系统应用。各 Android 版本中,该分区为:
- Android 8.1 及更低版本 -
/system
- Android 9 及更高版本 -
/system, /product, /vendor
在本页面中,/etc/permissions/priv-app
解析为 partition/etc/permissions/priv-app
。
过去,设备制造商几乎无法控制可对特权应用授予哪些签名|特许权限。从 Android 8.0 开始,制造商必须在 /etc/permissions
目录下的系统配置 XML 文件中明确授予特许权限。从 Android 9 开始,实现人员必须明确授予或拒绝授予所有特许权限,否则设备将无法启动。
privapp-permissions.xml
文件只有在与特权应用位于同一分区时才能授予或拒绝授予该应用权限。例如,如果 /vendor
分区上的应用请求特许权限,则只能由同样位于 /vendor
上的 privapp-permissions.xml
文件来同意或拒绝该请求。
添加白名单
应用的权限白名单可列在位于 frameworks/base/etc/permissions
目录下的单个或多个 XML 文件中,如下所示:
/etc/permissions/privapp-permissions-OEM_NAME.xml
/etc/permissions/privapp-permissions-DEVICE_NAME.xml
对于如何组织内容,没有严格的规则。设备实现人员可以决定内容结构,只要 /system/priv-app
下的所有应用均列入白名单即可。例如,Google 针对由 Google 开发的所有特权应用提供了一个白名单,并建议使用以下组织方式:
- 对于已包含在 Android 开源项目 (AOSP) 树中的应用,请将其权限列在
/etc/permissions/privapp-permissions-platform.xml
中。 - 对于 Google 应用,请将其权限列在
/etc/permissions/privapp-permissions-google.xml
中。 - 对于其他应用,请使用以下格式的文件:
/etc/permissions/privapp-permissions-DEVICE_NAME.xml
。
生成白名单
如需针对系统映像上可用的所有应用自动生成白名单,请使用位于以下位置的 AOSP 命令行工具:development/tools/privapp_permissions/privapp_permissions.py
。如需生成适用于特定设备的 privapp-permissions.xml
的初始版本,请执行以下操作:
- 构建系统映像:
. build/envsetup.sh
lunch PRODUCT_NAME
make -j
- 运行
privapp_permissions.py
脚本以生成一个privapp-permissions.xml
文件,该文件会列出所有需要列入白名单的签名|特许权限: 此工具会输出可在development/tools/privapp_permissions/privapp_permissions.py
/etc/permissions
目录路径下作为单个文件或拆分为多个文件的 XML 内容。如果设备的/etc/permissions
目录下已经包含白名单,则该工具将仅输出差异内容(例如,需要列入白名单但尚未列入的签名|特许权限)。这对审核也很有用,当添加新版本的应用时,该工具会检测所需的额外权限。 - 将生成的文件复制到相应的
/etc/permissions
目录下,系统将在启动过程中从这里读取这些文件。
自定义白名单
AOSP 包含可根据需要自定义的白名单实现。对于包含在 AOSP 中的应用,其权限已在 /etc/permissions/privapp-permissions-platform.xml
中列入白名单。
默认情况下,privapp_permissions.py
脚本会生成输出,自动授予特权应用所请求的任何权限。如果有不应授予的权限,请修改 XML,用“deny-permission”标记代替“permission”标记。示例:
<!-- 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> ...
查找缺少的权限
如需在启动新设备时查找缺少的权限,请启用过渡日志模式:
ro.control_privapp_permissions=log
违规行为会记录在日志文件中,但非特许权限仍将得到准许。这样,在提供违规行为列表的同时,设备仍能正常运行。下面是错误消息格式:
PackageManager: Privileged permission {PERMISSION_NAME} for package {PACKAGE_NAME} - not in privapp-permissions whitelist
必须将缺少的权限加入相应的白名单来解决所有违规行为。
- 在 Android 8.0 及更低版本中,受影响的应用即使位于
priv-app
路径中也不会被授予缺少的权限。 - 在 Android 9 及更高版本中,违规行为(缺少特许权限)意味着设备无法启动。您必须明确准许或拒绝授予所有特许权限。
执行白名单
白名单列好后,可设置 build 属性 ro.control_privapp_permissions=enforce
使其在运行时生效。