Android权限简介

  Android是运行在Linux内核上的,Android与Linux分别有自己的一套严格的安全及权限机制,在这里简单介绍一下Linux文件系统的权限与Android中如何获取system权限。

(一)linux文件系统上的权限

  下面是一个典型的linux文件系统权限说明:
    -rwxr-x--x system   system       4156 2012-06-30 16:12 test.apk.

 关于"-rwxr-x--x" 的权限说明

  • 第一个字符代表这个文件的类型(如目录、文件或链接文件等等):
  1. 当为[ d ]则是目录;
  2. 当为[ - ]则是文件;
  3. 若是[ l ]则表示为连结档(link file);
  4. 若是[ b ]则表示为装置文件里面的可供储存的接口设备(可随机存取装置);
  5. 若是[ c ]则表示为装置文件里面的串行端口设备,例如键盘、鼠标(一次性读取装置)
  • 接下来的字符中,以三个为一组,且均为『rwx』 的三个参数的组合< [ r ]代表可读(read)、[ w ]代表可写(write)、[ x ]代表可执行(execute) 要注意的是,这三个权限的位置不会改变,如果没有权限,就会出现减号[ - ]而已>
  1. 第一组为『相应的用户的权限』,以『test.apk』那个文件为例, 该文件的拥有者可读可写可执行;
  2. 第二组为『相应的用户组的权限』,不可读不可写可执行;
  3. 第三组为『其他人的权限』不可读不可写可执行.

关于"system system"的说明

  第一个表示的是相应的用户,就是说test.apk是属于system这个用户的文件;

  第二个表示的是相应的用户组。

关于"4156"的说明

  文件大小

关于"2012-06-30 16:12"的说明

  文件最新修改时间

  这些权限说明代表的是相应的用户/用户组及其他人对此文件的访问权限,与此文件运行起来具有的权限完全不相关。比如上面的例子只能说明system用户拥有对此文件的读写执行权限;system组的用户对此文件拥有读、执行权限;其他人对此文件只具有执行权限。而test.apk运行起来后可以干哪些事情,跟这个就不相关了。千万不要看apk文件系统上属于system/system用户及用户组,或者root/root用户及用户组,就认为apk具有system或root权限。apk程序是运行在虚拟机上的,对应的是Android独特的权限机制,只有体现到文件系统上时才使用linux的权限设置。

(二)Android的权限规则

(1)Android中的apk必须签名
  这种签名不是基于权威证书的,不会决定某个应用允不允许安装,而是一种自签名证书。重要的是,android系统有的权限是基于签名的。比如:system等级的权限有专门对应的签名,签名不对,权限也就获取不到。默认生成的APK文件是debug签名的。获取system权限时用到的签名见后面描述。

(2)基于UserID的进程级别的安全机制
  进程有独立的地址空间,进程与进程间默认是不能互相访问的,Android通过为每一个apk分配唯一的linux userID来实现,名称为"app_"加一个数字,比如app_43不同的UserID,运行在不同的进程,所以apk之间默认便不能相互访问。

  Android提供了如下的一种机制,可以使两个apk打破前面讲的这种壁垒。
  在AndroidManifest.xml中利用sharedUserId属性给不同的package分配相同的userID,通过这样做,两个package可以被当做同一个程序,系统会分配给两个程序相同的UserID。当然,基于安全考虑,两个apk需要相同的签名,否则没有验证也就没有意义了。

(3)默认apk生成的数据对外是不可见的
  实现方法是:Android会为程序存储的数据分配该程序的UserID。借助于Linux严格的文件系统访问权限,便实现了apk之间不能相互访问似有数据的机制。
  例:我的应用创建的一个文件,默认权限如下,可以看到只有UserID为app_21的程序才能读写该文件。
  -rw------- app_21   app_21      87650 2000-01-01 09:48 test.txt

  那么如何对外开放呢?

  • 使用MODE_WORLD_READABLE and/or MODE_WORLD_WRITEABLE标记。When creating a new file with getSharedPreferences(String, int), openFileOutput(String, int), or openOrCreateDatabase(String, int, SQLiteDatabase.CursorFactory), you can use the MODE_WORLD_READABLE and/or MODE_WORLD_WRITEABLE flags to allow any other package to read/write the file. When setting these flags, the file is still owned by your application, but its global read and/or write permissions have been set appropriately so any other application can see it.

 

(4)AndroidManifest.xml中的显式权限声明
  Android默认应用是没有任何权限去操作其他应用或系统相关特性的,应用在进行某些操作时都需要显式地去申请相应的权限。在应用安装的时候,package installer会检测该应用请求的权限,根据该应用的签名或者提示用户来分配相应的权限。在程序运行期间是不检测权限的。如果安装时权限获取失败,那执行就会出错,不会提示用户权限不够。大多数情况下,权限不足导致的失败会引发一个 SecurityException,会在系统log(system log)中有相关记录。

(5)权限继承/UserID继承
  当我们遇到apk权限不足时,我们有时会考虑写一个linux程序,然后由apk调用它去完成某个它没有权限完成的事情,很遗憾,这种方法是行不通的。前面讲过,android权限是在进程层面的,也就是说一个apk应用启动的子进程的权限不可能超越其父进程的权限(即apk的权限),即使单独运行某个应用有权限做某事,但如果它是由一个apk调用的,那权限就会被限制。实际上,android是通过给子进程分配父进程的UserID实现这一机制的。

 

(三)常见权限不足问题分析

  首先要知道,普通apk程序是运行在非root、非system层级的,也就是说看要访问的文件的权限时,看的是最后三位。另外,通过system/app安装的apk的权限一般比直接安装或adb install安装的apk的权限要高一些。
  言归正传,运行一个android应用程序过程中遇到权限不足,一般分为两种情况:
(1)Log中可明显看到权限不足的提示。
  此种情况一般是AndroidManifest.xml中缺少相应的权限设置,好好查找一番权限列表,应该就可解决,是最易处理的情况。
有时权限都加上了,但还是报权限不足,是什么情况呢?Android系统有一些API及权限是需要apk具有一定的等级才能运行的。比如 SystemClock.setCurrentTimeMillis()修改系统时间,WRITE_SECURE_SETTINGS权限好像都是需要有system级的权限才行,也就是说UserID是system.

 

(2)Log里没有报权限不足,而是一些其他Exception的提示,这也有可能是权限不足造成的。
  比如:我们常会想读/写一个配置文件或其他一些不是自己创建的文件,常会报java.io.FileNotFoundException错误。系统认为比较重要的文件一般权限设置的也会比较严格,特别是一些很重要的(配置)文件或目录。如
    -r--r----- bluetooth bluetooth      935 2010-07-09 20:21 dbus.conf
    drwxrwx--x system   system            2010-07-07 02:05 data

  dbus.conf好像是蓝牙的配置文件,从权限上来看,根本就不可能改动,非bluetooth用户连读的权利都没有。
/data目录下存的是所有程序的私有数据,默认情况下android是不允许普通apk访问/data目录下内容的,通过data目录的权限设置可知,其他用户没有读的权限。所以adb普通权限下在data目录下敲ls命令,会得到opendir failed, Permission denied的错误,通过代码file.listfiles()也无法获得data目录下的内容。上面两种情况,一般都需要提升apk的权限,目前我所知的apk能提升到的权限就是system。

 

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。