Android应用程序利用init.rc service获得root权限

发布于:想在android应用程序中动态mount一个NFS的系统,但是执行mount命令必须要root权限才可以。一般情况下,在Android的APK层是不能获得root权限的。

上一节提到实现由init启动的Service,来帮助Android应用程序执行root权限的命令或者实现一个虚拟设备,这个设备帮助Android应用程序执行root权限的命令。

  本文将会选择第一种来解决Android应用程序mount NFS文件系统的问题。

Init.rc Service

  在Android系统init.rc中定义很多Service,Init.rc中定义的Service将会被Init进程创建,这样将可以获得root权限。

  设置系统属性“ctl.start”,把“ctl.start”设置为你要运行的Service,假设为“xxx”,Android系统将会帮你运行“ctl.start”系统属性中指定的Service。那么运行结果init进程会写入命名为“init.svc.+xxx”的系统属性中,应用程序可以参考查阅这个值来确定Service xxx执行的情况。

Android系统属性(property)权限

   难道Android属性“ctl.start”不是所有进程都可以设置的,见property_service.c中的源码,设置Android系统属性的函数为handle_property_set_fd(),从源码中可以发现如果设置“ctl.”开头的Android系统属性,将会调用check_control_perms函数来检查调用者的权限,只有root权限和system权限的应用程序才可以修改“ctl.”开头的Android系统属性。否则将会检查control_perms全局变量中的定义权限和Service。从代码中可以看到,任何不以property_perms[] 中定义的前缀开头的property 是无法被除root以外的用户访问的,包括system用户。

实例

   下面以上面提出的mount nfs文件系统为例说明:

A.首先定义一个执行mount的脚本,我把它位于/system/etc/mount_nfs.sh,定义如下:

  1: #!/system/bin/sh

  2: 

  3: /system/bin/busybox mount -o rw,nolock -t nfs 192.168.1.6:/nfs_srv /data/mnt

不要忘了把它加上可执行权限。

B.在init.rc中加入一个Service定义,定义如下:

  1: service mount_nfs /system/etc/mount_nfs.sh

  2:    oneshot

  3:    disabled

C.让自己的应用程序获得system权限,方法见前面章节

D.在自己应用程序中设置System系统属性“ctl.start”为“mount_nfs”,这样Android系统将会帮我们运行mount_nfs系统属性了。不能够调用System.getProperty,这个函数只是修改JVM中的系统属性。只能调用android.os.SystemProperties,最终通过JNI调用C/C++层的API property_get和property_set函数。

  SystemProperties.set("ctl.start","mount_nfs");

E.最后在自己应用程序中,读取“init.svc.mount_nfs”Android系统Property,检查执行结果。代码如下:

 

1:while(true)
  2: {
  3:    mount_rt = SystemProperties.get("init.svc.mount_nfs","");
  4:    if(mount_rt != null && mount_rt.equals("stopped"))
  5:    {
  6:        return true;
  7:    }
  8:    
  9:    try
 10:    {
 11:        Thread.sleep(1000);
 12:    }catch(Exception ex){
 13:        Log.e(TAG,"Exception: " + ex.getMessage());
 14:    }
 15: }

    init进程维护一个service的队列,所以我们需要轮训来查询service的执行结果。

1. 文件(夹)读写权限

init.rc 中建立test1 test2 test3文件夹

mkdir /data/misc/test1 0770 root root   

mkdir /data/misc/test2 0770 wifi wifi

mkdir /data/misc/test3 0770 system misc

其中

test1 目录的owner是root, group也是root

test2 目录的owner是wifi , group也是wifi

test3 目录的owner是system , group是misc(任何用户都属于group misc)

 

service xxxx /system/bin/xxxx
    user root
    disabled
    oneshot
 
service yyyy /system/bin/yyyy
    user system
    disabled
    oneshot
 
service zzzz /system/bin/zzzz
    user wifi
    disabled
    oneshot

 

结果:

 

xxxx 服务可以访问 test1, test2, test3

yyyy 服务可以访问 test3

zzzz 服务可以访问 test2, test3

 

见android_filesystem_config.h中定义AID_ROOT  AID_SYSTEM  AID_MISC等宏定义的权限

360等特殊系统是否可以考虑在AID_ROOT和AID_SYSTEM之间加一个权限和用户,增加新的哦property给360用?

 

   通过上面的这些步骤,Android应用程序就能够调用init.rc中定义的Service了。这样你的Android应用程序也就获得了root权限。前提是Android系统开发人员,否则你无法修改init.rc等文件,而且应用程序必须要获得system权限。