探究Android权限动态检察机制

探究Android权限动态检查机制

一 Android权限

    一般来说,Android的APK包在安装时会向Android系统申请权限,用户在安装APK时会看到此APK索要的权限,用户要么全都批准,要么拒绝本次安装。Android的权限与Android的API对应,一个APK如果获得了某项权限,这就意味着它在运行时可以调用Android的Java API,从而实现对Android受限资源进行访问的目的。Android的权限主要包括三部分信息:权限名称,属于的组和保护级别。属于的组是指这个权限在一个权限组里。如何理解?切换到android源码framework\base\data\etc\platform.xml,如下图所示:

探究Android权限动态检察机制

比如第一个权限android.permission,BLUETOOTH_ADMIN,它所在的组是net_bt_admin。保护级别分为四种,Norma,Dangerous,Signature,SignatureOrSystem,不同的保护级别代表此权限的认证级别高低,后面两种要求申请权限的APK包具有和拥有此权限的APK包相同的数字签名。如果开发者在编制Android应用程序时想要使用某种权限,比如访问网络,那么必须在应用程序的AndroidManifest.xml文件中申请,形如<use-permissions>,同样Android应用程序的某个组件也可以设置访问权限,也就是说,如果另一个组件要想执行对设有访问权限组件的操作时,必须先获取此权限。

二 Android静态权限检查

    Android静态权限检查发生在安装包被解析后。Android的框架层代码frameworks\base\core\java\...\PackageParser.java负责解析APK包,并把解析到的信息保存起来,而对APK中AndroidManifest.xml文件所涉及的权限申请在框架层代码frameworks\base\services\java\com\android\server\pm\PackageManagerService.java中的grantPermissionsLPw方法中得以检查和批准:

if (bp.protectionLevel == PermissionInfo.PROTECTION_NORMAL
                        || bp.protectionLevel == PermissionInfo.PROTECTION_DANGEROUS) {
                    allowed = true;
                } else if (bp.packageSetting == null) {
                    // This permission is invalid; skip it.
                    allowed = false;
                } else if (bp.protectionLevel == PermissionInfo.PROTECTION_SIGNATURE
                        || bp.protectionLevel == PermissionInfo.PROTECTION_SIGNATURE_OR_SYSTEM) {
                    allowed = (compareSignatures(
                            bp.packageSetting.signatures.mSignatures, pkg.mSignatures)
                                    == PackageManager.SIGNATURE_MATCH)
                            || (compareSignatures(mPlatformPackage.mSignatures, pkg.mSignatures)
                                    == PackageManager.SIGNATURE_MATCH);

从以上的代码探究Android权限动态检察机制我们可以看出,Android对权限的保护级别进行了检查。方法grantPermissionLPw只属于权限的静态检查,并不涉及应用程序在运行时的权限检查。

三 Android动态权限检查

     Android会有动态权限检查吗?答案是有!这里的动态权限检查是指Android系统在APP运行时对App发起的某些操作或某些数据访问才进行的权限检查,其中就有一个方法checkUidPermission(String permName, int uid),它也在PackageMangerService.java中被定义。此方法是根据APP的UID和此时所提出的权限名permName进行检查方法很简单,首先根据uid找到APP在安装时所被批准的权限集,然后看看permName是不是在其中。

synchronized (mPackages) {
            Object obj = mSettings.getUserIdLPr(uid);
            if (obj != null) {
                GrantedPermissions gp = (GrantedPermissions)obj;
                if (gp.grantedPermissions.contains(permName)) {


四 实验验证动态权限检查

实验目的:试验checkUidPermission是否真的会在APP运行时进行权限检查?

实验方法:在以上代码第5行处在写一行代码:

if(uid >= 10000 && permName == "android.permission.CAMERA") {return PackageManager.PERMISSION_DENIED;}

以上代码是说只要有非系统用户申请了访问camera的权限,那么系统就拒绝。如果Android系统有权限动态检查,那么摄像功能是不能用了。

编译Android源码:

1. 模块编译

首先进行模块编译 切换到shell,切换到android的源码目录,输入:

source build/envsetup.sh
        lunch full-eng
        mmm frameworks\baser\service\java

这样只是编译java\这个模块,注意:java\必须有Android.mk文件,这相当与Linux的makefile

2. Android源码整体编译

在上述编译成功后,直接输入make

3. 运行模拟器

输入emulator,等模拟器跑起来,点击Camera程序,我们发现如下:

探究Android权限动态检察机制


摄像头没有被启动。而编译之前的Camera是能够开启摄像头的,如下:

探究Android权限动态检察机制

原因分析:当Camera被安装到Android系统后,Camera的APP就会被分配一个唯一的UID和GID,一般来说UID等于GID,每个APP运行在独立的沙箱(Dalvik虚拟机)里,因此,当此Camera的进程提出访问摄像设备时,到了Android框架层,checkUidPermission会被调用,从而拒绝本次访问,那么内核的进程也就无从访问此类设备了。