Android透传root权限控制

项目需求:特定应用需要用到root权限运行部分命令,如iptables等;


分解两部分:

1、开启系统服务,接收到cmd,然后调用xxxsu(私有root程序);

2、系统底层实现xxxsu服务,供上层调用


我这里负责系统底层实现;

1、先说明下root相关的内容在4.3的变化:

由于在Android4.3中,从如下的open Source Code :

dalvik_system_Zygote.cpp-》forkAndSpecializeCommon:


  1. #ifdef HAVE_ANDROID_OS
  2. extern int gMallocLeakZygoteChild;
  3. gMallocLeakZygoteChild = 1;

  4. /* keep caps across UID change, unless we're staying root */
  5. if (uid != 0) {
  6. err = prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);

  7. if (err < 0) {
  8. ALOGE("cannot PR_SET_KEEPCAPS: %s", strerror(errno));
  9. dvmAbort();
  10. }
  11. }

  12. for (int i = 0; prctl(PR_CAPBSET_READ, i, 0, 0, 0) >= 0; i++) {
  13. err = prctl(PR_CAPBSET_DROP, i, 0, 0, 0);
  14. if (err < 0) {
  15. if (errno == EINVAL) {
  16. ALOGW("PR_CAPBSET_DROP %d failed: %s. "
  17. "Please make sure your kernel is compiled with "
  18. "file capabilities support enabled.",
  19. i, strerror(errno));
  20. } else {
  21. ALOGE("PR_CAPBSET_DROP %d failed: %s.", i, strerror(errno));
  22. dvmAbort();
  23. }
  24. }
  25. }

  26. #endif /* HAVE_ANDROID_OS */

注意红色斜体的代码,这是4.3新加入的。新加入的这些代码,会导致setuid()接口不再起作用;


那么接下来,我使用的是现在主流的方法,就是在init进程中以root用户启动su --daemon进程,然后通过本地socket接收命令:

1、第一步,移植cm-13代码中的su,该su带有--daemon参数,支持服务的方式代理执行root权限的命令;

下载cm-13,将system/extras/su目录移植过来;改名xxxsu,直接覆盖更新su也行,以下以改名xxxsu为例说明;


2、修改system/core/include/private/android_filesystem_config.h文件,按照自己的权限控制要求修改可执行文件权限

{ 00750, AID_ROOT,      AID_SHELL,     0, "system/xbin/xxxsu" },


3、在init.rc中增加启动root代理服务:

# su daemon
service xxxsu_daemon /system/xbin/xxxsu --daemon
    seclabel u:r:xxxsudaemon:s0

on property:persist.sys.root_access=0
    stop xxxsu_daemon                                   
on property:persist.sys.root_access=1
    start xxxsu_daemon
然后在需要的位置通过setprop persist.sys.root_access 1 启动root服务


4、在external/sepolicy目录中增加xxxsu.te,增加对应的运行规则如下

type xxxsu_exec, exec_type, file_type;
type xxxsudaemon, domain;

# Domain used for su processes, as well as for adbd and adb shell
# after performing an adb root command.  The domain definition is
# wrapped to ensure that it does not exist at all on -user builds.
type xxxsu, domain, mlstrustedsubject;
domain_auto_trans(xxxxxx, xxxsu_exec, xxxsu)  #允许xxxxxx域执行xxxsu

# Make sure that dumpstate runs the same from the "su" domain as
# from the "init" domain.
#  domain_auto_trans(su, dumpstate_exec, dumpstate)

# su is also permissive to permit setenforce.
permissive xxxsu;
permissive xxxsudaemon;


5、至此,编译userdebug版本,在Android app上,应该已经能够能够通过以下代码运行命令了

String [] finalcmd={"xxxsu","-c",cmd};
Runtime runtime = Runtime.getRuntime();

当切换至user版本时,由于各种sepolicy规则限制,APP方面会出现运行失败的情况,这就需要我们根据自己的App的用户类型,制定不同的规则,让指定类型的app能够有运行权限;




你可能感兴趣的:(android平台开发)