Android 应用权限导致系统无法开机
一、问题发生的现象及日志打印
1.1 问题发生现象
开机向导中增加蓝牙、WIFI及设置时区的权限后,adb push到手机里面,重启手机无法开机,卡到开机动画界面,无法进入开机向导。
1.2 Log打印分析
从日志看应该是应用本身是priv级别的app,并且申请了BLUETOOTH_PRIVILEGE、WRITE_SECURE_SETTINGS、INTERACT_ACROSS_USERS和SET_TIME_ZONE,但是没有在权限白名单中添加,所以导致类似日志打印,最终会导致system server重启,系统无法开机。
11-10 07:03:49.084 2392 2392 W PackageManager: Privileged permission android.permission.BLUETOOTH_PRIVILEGED for package com.dten.setupwiard - not in privapp-permissions whitelist
11-10 07:03:49.085 2392 2392 W PackageManager: Privileged permission android.permission.WRITE_SECURE_SETTINGS for package com.dten.setupwiard - not in privapp-permissions whitelist
11-10 07:03:49.085 2392 2392 W PackageManager: Privileged permission android.permission.INTERACT_ACROSS_USERS for package com.dten.setupwiard - not in privapp-permissions whitelist
11-10 07:03:49.085 2392 2392 W PackageManager: Privileged permission android.permission.SET_TIME_ZONE for package com.dten.setupwiard - not in privapp-permissions whitelist// 进而会有如下日志打印,导致system server进程重启
10 06:13:08.174 2645 2645 E System : ******************************************
11-10 06:13:08.177 2645 2645 E System : ************ Failure starting system services
11-10 06:13:08.177 2645 2645 E System : java.lang.IllegalStateException: Signature|privileged permissions not in privapp-permissions whitelist: {com.dten.setupwiard: android.permission.WRITE_SECURE_SETTINGS, com.dten.setupwiard: android.permission.INTERACT_ACROSS_USER
S, com.dten.setupwiard: android.permission.BLUETOOTH_PRIVILEGED, com.dten.setupwiard: android.permission.SET_TIME_ZONE}
11-10 06:13:08.177 2645 2645 E System : at com.android.server.pm.permission.PermissionManagerService.systemReady(PermissionManagerService.java:2956)
11-10 06:13:08.177 2645 2645 E System : at com.android.server.pm.permission.PermissionManagerService.access$100(PermissionManagerService.java:122)
11-10 06:13:08.177 2645 2645 E System : at com.android.server.pm.permission.PermissionManagerService$PermissionManagerServiceInternalImpl.systemReady(PermissionManagerService.java:3017)
11-10 06:13:08.177 2645 2645 E System : at com.android.server.pm.PackageManagerService.systemReady(PackageManagerService.java:21902)
11-10 06:13:08.177 2645 2645 E System : at com.android.server.SystemServer.startOtherServices(SystemServer.java:2096)
11-10 06:13:08.177 2645 2645 E System : at com.android.server.SystemServer.run(SystemServer.java:539)
11-10 06:13:08.177 2645 2645 E System : at com.android.server.SystemServer.main(SystemServer.java:367)
11-10 06:13:08.177 2645 2645 E System : at java.lang.reflect.Method.invoke(Native Method)
11-10 06:13:08.177 2645 2645 E System : at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
11-10 06:13:08.177 2645 2645 E System : at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1050)
二、代码逻辑分析
根据报错日志定位到代码逻辑是PermissionManagerService.java(frameworks\base\services\core\java\com\android\server\pm\permission)中的grantSignaturePermission()方法
private boolean grantSignaturePermission(String perm, PackageParser.Package pkg, BasePermission bp, PermissionsState origPermissions) {.....//可以看到,如果该pkg对应的perm不在白名单中,则会下面加入过denied的列表中,导致下面的not in priv的日志打印if (!hasPrivappWhitelistEntry(perm, pkg)) { // Only report violations for apps on system image if (!mSystemReady && !pkg.isUpdatedSystemApp()) { // it's only a reportable violation if the permission isn't explicitly denied ArraySet<String> deniedPermissions = null; if (pkg.isVendor()) { deniedPermissions = SystemConfig.getInstance() .getVendorPrivAppDenyPermissions(pkg.packageName); } else if (pkg.isProduct()) { deniedPermissions = SystemConfig.getInstance() .getProductPrivAppDenyPermissions(pkg.packageName); } else if (pkg.isProductServices()) { deniedPermissions = SystemConfig.getInstance() .getProductServicesPrivAppDenyPermissions(pkg.packageName); } else { deniedPermissions = SystemConfig.getInstance() .getPrivAppDenyPermissions(pkg.packageName); } final boolean permissionViolation = deniedPermissions == null || !deniedPermissions.contains(perm); if (permissionViolation) { Slog.w(TAG, "Privileged permission " + perm + " for package " + pkg.packageName + " - not in privapp-permissions whitelist"); if (RoSystemProperties.CONTROL_PRIVAPP_PERMISSIONS_ENFORCE) { if (mPrivappPermissionsViolations == null) { mPrivappPermissionsViolations = new ArraySet<>(); } mPrivappPermissionsViolations.add(pkg.packageName + ": " + perm); } } else { return false; } } if (RoSystemProperties.CONTROL_PRIVAPP_PERMISSIONS_ENFORCE) { return false; } } } ...... }
由于上面条件,如果对应应用的perm不再权限白名单中,则会增加到deniedPermission中,后面在systemready中会抛出异常,导致system server进程重启。
private void systemReady() { mSystemReady = true; if (mPrivappPermissionsViolations != null) { throw new IllegalStateException("Signature|privileged permissions not in " + "privapp-permissions whitelist: " + mPrivappPermissionsViolations); } mPermissionControllerManager = mContext.getSystemService(PermissionControllerManager.class); mPermissionPolicyInternal = LocalServices.getService(PermissionPolicyInternal.class); }
所以问题的关键是hasPrivappWhitelistEntry方法,我们重点看下这个方法,该方法中如果是product下则权限白名单是从通过SystemConfig类中getProductPrivAppPermissions方法。
private boolean hasPrivappWhitelistEntry(String perm, PackageParser.Package pkg) { ArraySet<String> wlPermissions = null;....if (pkg.isProduct()) { wlPermissions = SystemConfig.getInstance().getProductPrivAppPermissions(pkg.packageName); } ....// Let's check if this package is whitelisted... boolean whitelisted = wlPermissions != null && wlPermissions.contains(perm); // If it's not, we'll also tail-recurse to the parent. return whitelisted || pkg.parentPackage != null && hasPrivappWhitelistEntry(perm, pkg.parentPackage);}
SystemConfig的getProductPrivAppPermissions方法很简单,只是返回mProductPrivAppPermissions 数据类型,是一个ArrayMap的数据结构,以应用包名为key,存储应用的priv-app 的权限白名单。
final ArrayMap<String, ArraySet<String>> mProductPrivAppPermissions = new ArrayMap<>();
到目前为止,逻辑就很简单了,重点看下mProductPrivAppPermissions是如何添加元素即可,根据代码逻辑,mProductPrivAppPermissions是通过系统在开机过程中读取/product/etc/permissions/ 、/vendor/etc/permissions/ 、/system/etc/permissions/ 下的xml文件所得。因此我们需要给开机向导应用增加对应的权限白名单。
三、解决方案思路
根据第二块的代码分析,解决思路就比较清楚了,关键是给开机向导app增加权限白名单。
3.1 第一种尝试
在privapp-permissions-platform.xml(frameworks/base/data/etc/)中增加如下代码,进行验证,adb push 到手机中进行验证,发现问题并没没有解决。
<permissions><privapp-permissions package="com.dten.setupwiard"><permission name="android.permission.SET_TIME_ZONE"/><permission name="android.permission.WRITE_SECURE_SETTINGS"/><permission name="android.permission.BLUETOOTH_PRIVILEGED"/><permission name="android.permission.INTERACT_ACROSS_USERS"/></privapp-permissions>
</permissions>
进一步分析代码,可以看到,不同目录下的应用对应的权限文件路径是不一样的,privapp-permissions-platform.xml文件被编译到/system/etc/permissions/下,所以只对/system/priv-app/下的应用有效果。而决定xml文件编译到那个路径下,是在frameworks/base/data/etc/Andoid.bp来决定的。
prebuilt_etc { name: "privapp-permissions-platform.xml",sub_dir: "permissions", src: "privapp-permissions-platform.xml",
} prebuilt_etc { name: "privapp_whitelist_com.android.settings", product_specific: true, sub_dir: "permissions", src: "com.android.settings.xml", filename_from_src: true,
}
3.2 第二种尝试
根据第一种尝试的分析,可以仿照com.dten.setting,我们创建一个com.dten.setupwiard.xml,并且在Android.bp中增加如下内容。
prebuilt_etc { name: "privapp_whitelist_com.dten.setupwiard", product_specific: true, sub_dir: "permissions", src: "com.dten.setupwiard.xml", filename_from_src: true,
}
如果觉得现在就ok了,可能会空欢喜一场,因为编译完,/product/etc/permissions/下面并没有生产com.dten.setupwiard.xml文件,根据android的编译规则,以及参考com.android.settings,应该是没有将其拷贝到out目录,所以需要在编译对应模块,比如编译com.dten.setupwiard的Android.mk文件中增加如下编译选项。
LOCAL_REQUIRED_MODULES := privapp_whitelist_com.dten.setupwiard
LOCAL_REQUIRED_MODULES的作用是当编译整个android 源码时,会将Mms模块在编译路径中依赖的module编译到out目录,并且打包,但是单独编译模块不会拷贝打包。
最后,编译完,烧录到设备中,可以成功开机。问题得到解决。
四、验证问题
验证问题主要有两种方式:
- 编译烧录版本进行验证,该方法比较耗时,但是相对准确,因为最终的方案还是需要编译到版本中验证
- 快速替换验证,使用adb 命令进行快速验证,前提是userdebug版本,并且Android 10.0以后,必须是非system目录下的文件,因为system目录,没法remount
五、参考文献
- https://zhuanlan.zhihu.com/p/147668734
Android 应用权限导致系统无法开机相关推荐
- 关于Android外设键盘导致系统输入法隐藏的解决方案
关于Android外设键盘导致系统输入法隐藏的解决方案 Android系统发展到今天,如果你还认为它只是应用于手机的话,那你就out了.现在很多企业在通过Android系统来定制他们的相应的设备 ...
- Android系统的开机画面显示过程分析(13)
WindowManagerService类的成员函数performEnableScreen的实现如下所示: public class WindowManagerService extend ...
- 【Android 逆向】Android 权限 ( Android 逆向中使用的 android.permission 权限 | Android 系统中的 Linux 用户权限 )
文章目录 一.Android 逆向中使用的 android.permission 权限 二.Android 系统中的 Linux 用户权限 一.Android 逆向中使用的 android.permi ...
- Android9获取权限闪退,Android 9.0 关于ACTION_CALL无权限导致闪退的问题
Android 9.0 关于ACTION_CALL无权限导致闪退的问题 18年年底毕业,开始从事android研发,对application层有兴趣,于是自学使用Android studio对app的 ...
- android 9.0 系统添加开机铃声
1.概述 在9.0的系统rom定制化开发中,在做一些项目中,有些产品需求要求添加开机铃声,就是在播放开机动画的过程中,播放开机音乐, 在原生系统中,是默认可以播放开机铃声的,接下来来分析下系统关于播放 ...
- 电脑计算机无法启动有还原和取消,win7系统提示配置windwos update失败还原更改导致电脑无法开机的三种解决方法...
win7系统每个一段时间都需要更新,有时候win7旗舰版系统遇到更新失败无法开机进入系统,怎么办呢?而且弹出提示"配置windwos update 失败还原更改,请勿关闭计算机", ...
- 黑鲨android的开机密码,黑鲨研习win10系统删除开机密码的处理步骤
随着电脑的使用率越来越高,我们有时候可能会遇到对win10系统删除开机密码的设置方法,想必大家都遇到过需要对win10系统删除开机密码进行设置的情况吧,那么应该怎么设置win10系统删除开机密码呢?我 ...
- AndroidUSB热敏打印机使用动态申请权限绕过系统权限对话框
AndroidUSB热敏打印机使用动态申请权限绕过系统权限对话框 最近在做超市收银系统,需要使用热敏打印机打印小票,记录一下踩过的坑.公司使用的是佳维视智能收银机与芯烨XP-D610L热敏打印机. 在 ...
- android应用权限杂谈
1 为什么Android总是事无巨细地告诉你应用索取的每一项权限? 相比Apple,Microsoft严格控制生态系统(从苹果给开发者的"App Store Guideline"可 ...
最新文章
- 使用合成数据集来做目标检测:目标检测的介绍
- python哪本好-在众多小说中,Python告诉你哪本小说好看
- Android开发之在Fragment和Activity页面拍照需要注意的地方
- 从零学web前端_从零到前端英雄(第1部分)
- oracle中sequence详解
- 『ORACLE』SPM(下)-baseline实验(11g)
- jeecg导出Excel
- 学习ubuntu之wget命令
- 1.3-----Simplify 3D切片软件简单设置
- 深度学习 简介 综述
- canvas画钟表demo
- 常用的做外链方法总结
- 海通股票交易接口查询当日成交c++源码分享
- 微信小程序用vant自定义tabbar页面并跳转相应页面
- 点击网页弹出窗口的js代码
- 千呼万唤始出来——uFUN开发板2.0开箱评测
- win10计算机睡眠 隔几分钟就唤醒,win10睡眠2秒后自动唤醒
- 雅思听力常见人名及地名(常考,必备)
- CSAPP Lab:attacklab
- Ali,Tencent遭反垄断罚款!巨头们的蛮长时代要结束了?