详解Android 安全机制
permission ,那么将该 permission 清除。
第九步。对每一个 package 进行轮询,并进行 permission 授权。
1. 对申请的权限进行检查,并更新 grantedPermissions 列表
2. 如果其没有设置 shared user id ,那么将其 gids 初始化为 mGlobalGids ,它从 permission.xml 中读取。
3. 遍历所有申请的权限,进行如下检查
1 )如果是该权限是 normal 或者 dangerous 的。通过检查。
2 )如果权限需要签名验证。如果签名验证通过。还需要进行如下检查
* 如果程序升级,而且是 system package 。那么是否授予该权限要看原来的 package 是否被授予了该权限。如果被授予了,那么通过检查,否则不通过。
* 如果是新安装的。那么检查通过。
4. 如果 3 中检查通过,那么将这个 permission 添加到 package 的 grantedPermissions 列表中,表示这个 permission 申请成功( granted)。申请成功的同时会将这个申请到的 permission 的 gids 添加到这个 package 的 gids 中去。
5. 将 permissionsFixed 字段标准为 ture ,表示这个 packge 的 permission 进行过修正。后续将禁止对非 system 的 app 的权限进行再次修正。
2.1.3 Dynamic permission 的管理
PackageManagerService 提供了 addPermission/ removePermission 接口用来动态添加和删除一些权限。但是这些权限必须是所谓的动态权限( BasePermission.TYPE_DYNAMIC )。
一个 Package 如果要添加 Dynamic permissions ,首先必须要在 manifest 中申明 permission-tree> 标签,它实际上是一个权限的名字空间(例如,“ com.foo.far ”这个权限就是 permission-tree “com.foo ”的成员),本身不是一个权限。一个 Package 只能为自己的 permission-tree 或者拥有相同的 uid 的 package 添加或者删除权限。
Package 不能够通过这种接口去修改在 manifest 中静态申请的权限,否则抛出异常。
首先查找这个 permission 在全局 permission 列表 mSettings.mPermissions 中是否存在。如果存在,而且类型为BasePermission.TYPE_DYNAMIC 那么根据传入的权限信息修改全局表中的权限信息,并触发 permissions.xml 的持久化。
如果在全局的 permission 列表 mSettings.mPermissions 中没有找到,先找到这个 permission 所在 permissionTree ,然后添加到全局permission 列表 mSettings.mPermissions 中去,并触发 permissions.xml 的持久化。
2.1.4 Uri permission 的管理
下面两个 接口 主要用于 Uri permission 的管理 (其实现在 ActivityManagerService 中)。
// 为指定的 uid 和 targetPkg 添加对某个 content Uri 的读或者写权限。
public void grantUriPermission(IApplicationThread caller, String targetPkg, Uri uri, int mode) throws RemoteException;
// 清除所有通过 grantUriPermission 对某个 Uri 授予的权限。
public void revokeUriPermission(IApplicationThread caller, Uri uri, int mode) throws RemoteException;
grantUriPermission 主要的实现过程分析。
grantUriPermission 分析:
1. 验证 caller 的 ProcessRecord 和 targetPkg 不为空。否则检测不通过。
2. 验证所请求的 mode 为 Intent.FLAG_GRANT_READ_URI_PERMISSION 或者为 Intent.FLAG_GRANT_WRITE_URI_PERMISSION ,否则不通过。
3. 确保参数 Uri 是一个 content Uri 。否则,则检测不通过。
4. 通过 Uri 得到目标 ContentProvider ,如果不存在,则检测不通过。
5. 从 PackageManagerService 中获得 targetPkg 对应的 uid 。
6. 检查 target uid 所对应的 package 是否真正需要这个权限?
先判断要申请的是读还是写权限,然后查看对应的 ContentProvider 中对应的 readPermission writePermission 字段是否保存了权限名称。如果该字段不为空,则以 target uid 和该权限名去PackageManagerService 中去查找该 uid 是否被 granted 了该权限。如果已经获得了该权限,那么无需再去为这个 Activity 去申请这个 Uri 权限了,返回。否者继续执行如下操作。
7. 检查这个 ContentProvider 的 grantUriPermissions 开关变量,是否允许对其它 package 进行权限的 grant 操作。如果禁止,那么抛出异常。
8. 检查这个 ContentProvider 是否设置了 Uri 的过滤类型 uriPermissionPatterns ,如果设置了过滤类型,则将需要申请权限的 Uri 与之匹配。匹配不同过,则抛出异常。
9. 检查调用者自己是否有权限访问这个 Uri 。如果没有,抛出异常。
10. 从 mGrantedUriPermissions 中取得 target ui
- Palm Pre拆解:剖析电池及多点触控问题(12-16)
- 用充电IC实现手机快速充电(11-17)
- 电池供电的IoT世界中的USB连接(12-21)
- 如此简单!两招教你轻松搞定Android手机耗电问题(12-08)
- 一种手机端的Android驾驶辅助系统的设计(12-07)
- 入门专用,Android应用程序中常用传感器的使用(12-05)
