android权限管理

来源:互联网 发布:淘宝互刷平台686 编辑:程序博客网 时间:2024/05/21 17:42
问题
今天尝试用一个android application读写网卡的mac地址,java层通过jni用ioctl命令。在将apk放在/system/app中、设置platform签名凭证、以及设置shareUid后,发现设置MAC地址(ioctl(SIOCSIFHWADDR))总是有权限问题,而读取MAC地址(ioctl(SIOCGIFHWADDR))则正常。

kernel检查
跟踪到kernel中net/core/dev.c,在函数dev_ioctl中,会检查CAP_NET_ADMIN权限:

if (!capable(CAP_NET_ADMIN))
  return -EPERM;


进入这个函数,发现检查的是进程是否在group AID_NET_ADMIN中:

if (cap == CAP_NET_ADMIN && in_egroup_p(AID_NET_ADMIN))
  return 0;


这里AID_NET_ADMIN跟android在init中的权限定义有些类似。

android权限定义
在system/core/include/private/android_filesystem_config.h中,android定义了一组uid和gid,如AID_ROOT, AID_SYSTEM, AID_NET_ADMIN。每一个id对应有字符串,如root, system, net_admin。当用户程序需要访问受限资源是,需要保证自己加入到对应的group中。

我在frameworks中搜索net_admin,没有找到任何文件。搜索蓝牙权限net_bt_admin时,找到了文件/etc/permissions/platform.xml。这里存放有AndroidManifest.xml中权限与底层权限的对应关系:

<permission name="android.permission.BLUETOOTH_ADMIN" >
    <group gid="net_bt_admin" />
</permission> 


我想,当开发者在AndroidManifest.xml中申请权限时,framework会通过platform.xml将它对应到net_bt_admin,进而确定所属组AID_XXX。这样,每个apk就有不同的权限。

另外,在android_filesystem_config.h,还可以看到为某些特定目录和特定文件静态设置的group,如/system/bin/ping加入了AID_NET_RAW。

尝试
我在platform.xml的android.permission.INTERNET权限下加入了group net_admin,使它变成:

<permission name="android.permission.INTERNET" >                    
    <group gid="inet" />                                          
    <group gid="net_admin" />                                            
</permission> 


然后,在AndroidManifest.xml中请求权限android.permission.INTERNET。重启系统后运行apk,发现可以修改mac了!


apk文件的group设置
PackageManagerService构造函数会解析platform.xml,建立android权限和gid的对应关系。然后,扫描apk时,会由请求的权限找到对应的gid,并保存在Package类中。

PackageManagerService()
  readPermissions(); /* 解析/etc/permissions/platform.xml */
    readPermissionsFromXml()
      readPermission() /* 建立permisstion名字与gid的关系,放在map mSettings.mPermissions中*/
  scanDirLI() /* 扫描/system/app, /data/app */
  updatePermissionsLP()
    grantPermissionsLP()

      

grantPermissionsLP()
{
  final PackageSetting ps = (PackageSetting)pkg.mExtras;

  /* gp 指向ps,即pkg的PackageSetting成员 */
  final GrantedPermissions gp = ps.sharedUser != null ? ps.sharedUser : ps;

  /* 设置gid */
  gp.gids = mGlobalGids;

  /* 如果package请求了permission, 则根据permission的protectionLevel决定是否要授予特定的gid,加入到gids中 */
} 


protectionLevel有4种:
normal - 安装时即授予权限,不需要确认
dangerous - 危险的权限,需要用户确认授予
signature - 安装的app需要与声明该权限的app有相同的signature
signatureOrSystem - 拥有相同的signature,或者放在system image中

比如拿android.permission.WRITE_SECURE_SETTINGS来讲,即使用户在app中声明的该权限,如果不把它放在system中,或者用platform key签名的话,android是不会授予该权限的。因为,在声明该权限的地方,即frameworks/base/core/res/AndroidManifest.xml中,该权限被声明为signatureOrSystem,而该app是用platform key签名的。

不管怎样,根据实际情况,android会给app授予一定的用户组。具体来说,apk的group信息是保存在pkg.mExtras中。在启动apk是,可以看到adb打印:

I/ActivityManager(  134): Start proc com.android.settings for activity com.android.settings/.Settings: pid=792 uid=1000 gids={3003, 3005, 3002, 3001}


后面的{3003, 3005, 3002, 3001}就是所在的组的id列表。