Android系统权限及签名

Android权限及签名

引子

现象:系统中的一个定制Service,服务是对外开放的,使用系统签名

LOCAL_CERTIFICATE := platform

应用层调用这个系统服务,获取底层的一些信息。如果在IDE里进行开发,普通签名,无法调用到该服务,
改成在系统编译环境里编译,并在Android.mk中加入如下语句:

LOCAL_CERTIFICATE := platform

android:sharedUserId="android.uid.system“
android:process="com.android.phone"

就可以顺利的获取到系统服务。其内在的原因是什么?

Linux权限

说起Android的权限和签名,就要先从Linux的权限说起,我们都知道Linux的文件系统是有权限限制的,对于每一个文件或者目录,我们执行
ls -l 指令都会看到类似如下的显示:
-rw-r–r– 1 xxxxx xxxxx 681 2013-05-24 09:16 Android.mk
分别代表:文件种类和权限;硬链接个数;User;Group;大小;最后访问/修改时间;文件/目录名
文件权限代表是否对对应用户,用户组,其他用户开放读或者写权限。而User;Group则是代表了该文件是属于谁的,比如用户ABC创建的一个文件,该文件的User则为ABC。linux就是通过文件权限和用户用户组这种方式来保证安全的。
而文件权限是通过进程来体现的,用户访问一个文件,总是要通过进程来访问,即便是打开一个终端界面,也是打开了一个bash进程来查看文件的。
就如下图所示:
图1
这里写图片描述

对于Android而言,启动一个Application,一般同样要启动一个单独的进程来运行,就像这样:

drwxr-x--x u0_a49   u0_a49            2013-01-01 08:00 com.example.test
drwxr-x--x radio    radio                  2013-01-03 06:35 com.android.phone

上面的test应用启动了一个单独的进程,它的用户的用户组都是u0_a49。这样如果没有意外的话,其只能访问到该应用自己的data数据。
问题来了,如果我想访问其他不适自己data的文件及目录该怎么办呢?首先想到的就是能不能把自定义的应用的用户组改成和其他某应用一样呢?比如User改成radio。

答案是可以的。不过Android为了保证系统安全,还有个规定:
必须在AndroidManifest.xml具有相同签名+相同shareUserId属性的两个App,才可以分配相同的用户ID。因为com.android.phone是系统应用,其签名是LOCAL_CERTIFICATE := platform 系统签名,所以我必须同样采用LOCAL_CERTIFICATE := platform系统签名,并且android:sharedUserId=”android.uid.radio” 才可以让这个自定义的App和phone应用具有相同的UID。(当然如果只是想访问,android:sharedUserId可以设为更高权限的用户也可以实现)。

AndroidManifest.xml中还有一个标签android:process,比如:android:process=”com.android.phone”,它可以单独应用于某个Activity或者Service,也可以直接应用于Application。作用就是将对应的Activity或者Service放在com.android.phone这个进程中运行。而使用这个标签的前提就是前一段所说的:具有相同签名+相同shareUserId属性。
标签android:process的作用比如phone应用中运行的某个动态库或者持有的某个单例对象,如果另外一个app想要使用或者说调用的话,是没法使用,或者拿到的是另外一个单例—因为是另一个进程了。这个时候通过android:process将对于的Activity让其在phone进程中运行。这样就可以很方便的使用phone应用中的资源了。
图2
这里写图片描述

签名和APK的关系:通常APK对于的是Linux中的User和Process。APK的运行,就代表一个独特的进程的运行,而该进程又属于某个User。具有相同签名和相同shareUserId属性的两个APK,才会属于同一个User.(APK安装时,PackageManagerService会检查)
签名和权限的关系:签名是为了让系统识别是不是同一个作者,除了前面提到的系统签名外,每个作者都可以自定义自己的签名。对于签名级的权限,比如一个作者的应用定义了一个权限。并设置权限的android:protectionLevel 为”signature”。那么只有该作者使用同样签名的另一个应用,才可以使用该权限。

Root后的手机呢

为什么root后就可以无视那些权限呢?
拿一个root过得手机,执行如下代码:

Process process = Runtime.getRuntime().exec("su");
os = new DataOutputStream(process.getOutputStream());  
os.writeBytes(“echo 1500000 > /sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq" + "\n"); 

su程序的权限如下所示:

System/bin/su
-rwsr-xr-x root root 

关键就是那个执行权限标志位S,代表当任何用户执行该文件时,都拥有该文件所有者的权限—–root。
当然这里说的比较简略,其实在应用执行root权限操作的时候,向Superuser.apk申请超级用户请求,
Superuser.apk利用系统漏洞,执行类似如下的操作。让su程序居然这些功能。

cp /data/tmp/su /system/bin/
chown root:root su 
chmod 4775 /system/bin/su 

这样上面修改cpu频率的语句就可以顺利执行。

Q&A

Q:android:sharedUserId和android:process的关系?
A:sharedUserId是对整个apk而言, android:process则是对某一个activity或者servicce而言,很多时候sharedUserId是android:process的前提
Q:android:sharedUserId和android:process分别对应用来说有什么作用。
A:sharedUserId可以让应用的uid变成类似system,phone,虽然没有root用户权限高,但是也可以做很多事了,具体要看其需求。具有phone的uid,然后才可以设定应用内的activity的android:process属性。
使用android:process的原因很多:
a)比如Stk应用,想要使用CatService(单例模式),于是它调用CatService.getInstance(),调用时如果已经存在CatService实例才会正确返回,该实例还没有建立,是拿不到的。而这个CatService是在Phone应用中,使用CommandsInterface 对象(Ril)作为参数建立。这是就需要把Stk应用放在Phone进程里,才可以拿到CatService实例。
b)又或者想要设计一个系统应用,想要调用Phone  phone = PhoneFactory.getDefaultPhone()获得Phone对象,但是这个调用只能运行在phone进程中(原因见该函数源码)。这就必须把调用该语句的activity设为android:process=“com.android.phone“——如Setting里的IccLockSettings。

发布了88 篇原创文章 · 获赞 5 · 访问量 9万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章