android 权限机制分析

一、划分用户名和对应的uid

1. 用户名和对应的uid

Android/system/core/include/private/android_filesystem_config.h

staticconst struct android_id_info android_ids[] = {

    { "root",          AID_ROOT, },

 

    { "system",        AID_SYSTEM, },

 

    { "radio",         AID_RADIO, },

    { "bluetooth",     AID_BLUETOOTH, },

    { "graphics",      AID_GRAPHICS, },

        {"input",         AID_INPUT, },

}

 

2. 用户uid 和uid定义,对应进程的uid,可以从进程中查看出来

 

$cat proc/1025/status

    我们可以看到其中有一段

    Name:   live.androidpad

    Uid:   10040    10040    10040    10040

    Gid:   10040    10040    10040    10040

    Groups:   1007 1015 3003

 

Android/system/core/include/private/android_filesystem_config.h

 

/* Thisis the master Users and Groups config for the platform.

*/

#defineAID_ROOT         0 /* traditional unix root user */

#defineAID_SYSTEM        1000  /* system server */

#defineAID_RADIO         1001  /* telephony subsystem, RIL */

#defineAID_BLUETOOTH     1002  /* bluetooth subsystem */

#defineAID_GRAPHICS      1003  /* graphics devices */

#defineAID_INPUT         1004  /* input devices */

#defineAID_DHCP          1014  /* dhcp client */

#define AID_VPN           1016 /* vpn system */

 

3. 定义每个uid 对应的service 权限

Android/system/core/init/property_service.c

 

/* Whitelist of permissions for setting property services. */

struct {

    const char *prefix;

    unsigned int uid;

    unsigned int gid;

}property_perms[] = {

    { "net.rmnet0.",      AID_RADIO,    0 },

    { "net.gprs.",        AID_RADIO,    0 },

    { "net.ppp",          AID_RADIO,    0 },

    { "net.qmi",          AID_RADIO,    0 },

}


以下转自:http://www.cnblogs.com/senix/archive/2013/01/15/2853733.html


第一章 Android的权限机制

    Android是基于Linux的系统,其权限访问控制自然离不开Linux的权限访问控制,而在第一章当中,将分成两个部分来剖析Android的权限控制系统。

一. Linux权限机制
     Linux的权限访问是由进程(访问者)和文件(被访问者)两部分组成的。其中相当一部分内容参考至APUE[1]。

1.1 Llinux文件权限
     我们在Linux当中输入命令    

$ls -l

我们可以看到这样类似如下的结果

drwxr-xr-x 2 root root 4096 11月 28 08:32 bin
drwxr-xr-x 3 root root 4096 12月 18 09:18 boot
drwxr-xr-x 2 root root 4096 3月 18 2012 cdrom
drwxr-xr-x 15 root root 4380 1月 4 19:28 dev
drwxr-xr-x 176 root root 12288 1月 4 19:01 etc
drwxr-xr-x 3 root root 4096 4月 16 2012 home

    第一列使用的如drwxr-xr-x的10位字段,表示的是该文件的文件类型和其权限。下表描述了各个标志位的含义

9 6 - 8 3 - 5 0 - 2
文件类型 拥有者访问权限 所在用户组访问权限 其它用户访问权限

p 管道文件

d 目录文件

l 符号连接文件

- 普通文件

s socket文件

c 字符设备文件

b 块设备文件

分别为读写执行权限,

-表示没有该位上的权限

读取权限: r

写入权限: w

执行权限: x

              s,S 表示设置了SUID位.

              s表示该原标志为x,

              S表示该原标志为-

分别为读写执行权限,

-表示没有该位上的权限

读取权限: r

写入权限: w

执行权限: x

              s,S 表示设置了GUID位.

              s表示该位原标志为x,

              S表示该位原标志为-

分别为读写执行权限,

-表示没有该位上的权限

读取权限: r

写入权限: w

执行权限: x

              s,S 表示设置了Sticky位.

              s表示该位原标志为x,

              S表示该位原标志为-

表1 Linux文件权限标识符

    特殊权限SGID标志位:普通文件设置了该标志位,则表示该进程的egid变成被运行的程序的所有者的gid。没有设置该位,则进程的egid为运行该程序的用户的gid。
    特殊权限SUID标志位:普通文件设置了该标志位,则表示该进程的euid变成被运行的程序的所有者的uid。没有设置该位,则进程的euid为运行该程序的用户的uid。 
    特殊权限Sticky标志位:旧的UNIX系统定义该位为指示操作系统在程序退出后,保留程序的代码段到swap空间。而在linux系统当中,该位表示防删除位,意味着该位被设置之后,只有文件的拥有者和root用户才能删除该文件。[1][2]

    SGID和SUID的存在意义在于,当一个非特权进程可以通过执行设置了SGID和SUID标志的程序,来获得特定权限。例如su,当它没有设置SGID和SUID标志位的时候,实际上它是不能创建一个具有root权限的shell进程的。

    以上的文件权限标识符在Linux当中实际上是使用二进制来表示的,例如rwxrw-rw-,转成二进制形式就是111110110,但实际情况下,我们为了更方便阅读,我们使用的是八进制进行标识,也就是766。但是文件标识符当中除了基本读写执行之外,再算上特殊权限,实际上Linux权限访问控制使用的是12位二进制数字(3位特殊权限 + 9位基础权限)来表示访问权限。比如rwsrw-rw-,转化成八进制表示方式,就是4766。

1.2 linux进程权限
    假设,我们在系统当中运行了一个程序,然后我们通过ps命令进行查询,得知该进程的pid为1025,之后我们在linux当中输入命令

$cat proc/1025/status

    我们可以看到其中有一段

    Name:    live.androidpad
    Uid:    10040    10040    10040    10040
    Gid:    10040    10040    10040    10040
    Groups:    1007 1015 3003

    其中,Uid行有四列,它们分别为RUID,EUID,SUID,FSUID
    RUID(实际用户id:Real User ID):进程的创建用户。
    EUID(有效用户id:Effective User ID):进程的有效用户,用于权限访问控制。
    SUID(保存设置用户id:Saved Set-User-ID):在程序执行(exec)之后作为EUID的副本,用于进程切换自己的EUID时使用,对用户来说实际意义不大。参考[1]
    FSUID(文件系统用户id:File System User ID):Linux新引进的一类用户、组,用于文件访问控制。(推测,文件访问上FSUID优先于EUID)
    Gid行有四列,它们分别为RGID,EGID,SGID,FSGID
    RGID(实际用户id:Real User ID):进程的创建用户组
    EGID(有效用户id:Effective User ID):进程的有效用户组,用于权限访问控制。
    SGID(保存设置用户id:Saved Set-User-ID):在程序执行(exec)之后作为EGID的副本,用于进程切换自己的EGID时使用,对用户来说实际意义不大。参考[1]
    FSGID(文件系统用户id:File System User ID):Linux新引进的一类用户、组,用于文件访问控制。(推测,文件访问上FSGID优先于EGID)
    Groups行是组id,里面是一组使用空格分开的数字,这些数字就是是用户组的id,它同样用于权限访问控制。

    对于FSGID和FSUID,这个东西是Linux中引进的,很多时候它的值是直接复制EGID和EUID的。而Unix系统当中,RUID\EUID\SUID、RGID\EGID\SGID和Groups作为标配,我们这里只讨论进程的这7个参数。正如我们使用命令输出的结果一样,除了Groups参数使用整形数组来表示之外,其余6个参数在Linux系统当中使用的都是整形来表示。而,这几个参数都会决定进程的权限等特性,而它们是基于什么规则来赋值的呢?

    虽然实际上跟文件访问权限有关的仅仅是EUID、EGID和Groups,但是因为文章的受众很可能是只了解Android系统的开发者,所以我这里也多讲一些。Linux当中所有的进程创建都是通过fork函数创建的,当进程被fork之后,子进程会继承父进程的RUID\EUID和RGID\EGID,而SUID和SGID会在exec之后作为EUID和EGID的副本被赋值(关于fork和exec的更多讲解,请参考APUE[1]和[3])。而在进程创建之后,子进程可以通过setuid和setgid修改自身的RUID\EUID\SUID、RGID\EGID\SGID,但是这是有固定规则的。

    以下是setuid的使用规则,setgid也与之类似:

    1.若进程拥有超级权限,则setuid函数将RUID\EUID\SUID设置为uid。

    2.若进程没有超级权限,而uid的值等于RUID或者SUID,则setuid将会把EUID设置为uid。而不会改变RUID或者SUID的值。

    3.如果上述两个条件都不满足,则返回失败。

1.3 Linux的权限访问控制

    这部分很简单,所有的系统调用最终都到内核当中,内核作为管理中枢,对所有的文件访问调用进行了核查。而APUE描述了内核对读写执行权限的测试算法:
    1.若进程的EUID是0,则允许访问。
    2.若进程的EUID等于所有者ID,那么:若所有者对应的访问权限位被设置,则允许访问,否则拒绝访问。
    3.若进程的EGID或者附加组ID之一等于文件的组ID,那么:若组对应的访问权限位被设置,则允许访问,否则拒绝访问。
    4.若其它用户对应的访问权限位被设置,则允许访问,否则拒绝访问。

二. Android权限机制
    原本想对这部分内容进行详细解析的,但后来发现涉及的内容包含了PKMS,AMS,应用程序安装,应用程序启动等内容。假若我来描写这些内容,第一,篇幅太多,第二,自己的描述能力有限容易误导别人。所以我就不深入说了,有兴趣的朋友可以参考[4][5][6]。

    在这里我们只需要知道,Android的策略是这样的:

    1.文件和设备访问,使用Linux的权限访问控制。部分权限声明之后,应用程序启动的时候,AMS会从PKMS那里获得该应用进程的uid,gid和组id信息,然后通过Zygote来创建一个指定id的进程。获得指定组id的进程,也会获得部分文件的访问权限,例如声明android.permission.WRITE_EXTERNAL_STORAGE来访问sdcard会被赋予sdcard_rw的组id。权限所对应的组id在frameworks/base/data/etc/platform.xml当中。

    特别注意:第一章也描述了,内核检查id的顺序是EUID然后再到EGID和组ID,所以,当你声明android.permission.WRITE_EXTERNAL_STORAGE的同时,声明shareUserId为system,是没有读写sdcard权限的。

    2.Android接口调用控制,首先是root用户和system用户拥有所有的接口调用权限,然后对于其它用户使用Context以下这几个函数来实现  

Context.checkCallingOrSelfPermission(String);
Context.checkCallingOrSelfUriPermission(Uri, int );
Context.checkCallingPermission(Permission);
Context.checkCallingUriPermission(Uri, int );
Context.checkPermission(String, int , int );
Context.checkUriPermission(Uri, int , int , int );
Context.checkUriPermission(Uri,String,String, int , int , int );
 
Context.enforceCallingOrSelfPermission(String,String);
Context.enforceCallingOrSelfUriPermission(Uri, int ,String);
Context.enforceCallingPermission(String,String);
Context.enforceCallingUriPermission(String,String);
Context.enforcePermission(String, int , int ,String);
Context.enforceUriPermission(Uri, int , int , int ,String);
Context.enforceUriPermission(Uri,String,String, int , int , int ,String);

    其中check开头的,只做检查。enforce开头的,不单检查,没有权限的还会抛出异常。

    这几个函数最后会调用到PKMS的checkUidPermission,该函数通过对比应用权限信息来判断该应用是否获得权限。

    3.Android权限等级划分为normal,dangerous,signature,signatureOrSystem,system,development,其中

    signature需要签名才能赋予权限,

    signatureOrSystem需要签名或者系统级应用(放置在/system/app目录下)才能赋予权限,

    system系统级应用(放置在/system/app目录下)才能赋予权限,系统权限的描述在frameworks/base/core/res/AndroidManifest.xml当中。

    这就解答了,为什么有时候声明一些权限没有起作用,例如android.permission.WRITE_MEDIA_STORAGE。

 

    如果我们想知道某个权限怎么使用,有什么制约怎么办?

pm list permissions -f

   来查看系统所有权限的描述

 

    如果我们需要在系统中增加一个权限,怎么办?那我们照下列的步骤来做

    1.确定你的权限属于文件访问控制,还是接口调用控制。

    2.在frameworks/base/core/res/AndroidManifest.xml,中增加你的权限描述。

    3.如果是文件访问控制,那就在frameworks/base/data/etc/platform.xml为你的权限依附指定的组id。

    4.如果是接口调用控制,那就在你的接口调用里面,加入上述Context检查权限的函数。

    

    (这段内容确实不大好写,酝酿了好久,再酝酿就胎死腹中了,再度吐槽一下自己的描述能力。:-)第二章内容会讲述一下Android root的原理。)


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
安卓系统的安全性主要从以下几个方面考虑: 1. 应用程序安全:应用程序是安卓系统最常用的组件之一,应用程序的安全性直接影响到整个系统的安全。安卓系统提供了一系列的应用程序安全机制,如应用签名校验、权限管理、Sandbox机制等,以保证应用程序之间的互相隔离。 2. 权限管理:安卓系统采用了基于权限的安全管理模式,通过权限管理机制,实现对系统资源进行访问控制。每个应用程序都需要在安装时声明需要访问哪些系统权限,用户可以根据应用程序的权限需求进行选择,从而保证了系统安全。 3. 内核安全:内核是安卓系统的核心组件之一,也是最重要的组件之一,内核安全直接关系到整个系统的稳定和安全。安卓系统采用了基于Linux内核的设计,Linux内核本身就具有较高的安全性,同时还对Linux内核进行了大量的修改和优化,增加了一些安卓特有的安全机制,如SEAndroid安全增强机制等。 4. 数据安全:数据安全是安卓系统的重要组成部分,数据安全涉及到数据存储、加密、传输等方面。安卓系统提供了一系列的数据安全机制,如存储加密、传输加密、PIN码保护等,以保证数据不被非法获取。 5. 网络安全:安卓系统是一个联网的操作系统,网络安全也是系统安全的一个重要方面。安卓系统采用了一系列的网络安全机制,如SSL协议、VPN等,以保证网络数据传输的安全性。 总之,安卓系统的安全性是一个综合性的问题,需要从多个方面进行考虑和保护。随着安卓系统的不断发展和完善,相信安卓系统的安全性会越来越高。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值