SickWorm的博客

给 Android ROM(AOSP)集成 SuperSU 的方法

Android, Android Rom  ·  

本文实验配置:

ROM: AOSP Android-6.0.1_r77
设备:Nexus 5
SuperSU: SR5-SuperSU-v2.82-SR5-20171001224502.zip

SuperSU 官方下载链接:https://download.chainfire.eu/1220/SuperSU/

处理 SELinux

我们给 Android 编译 ROM 的时候,可以编译出带有 root 权限的版本。但是由于 Android 4.4 以上 SELinux 的存在,apk 还是无法获得 root 权限,这样很多 root app 都会提示无法获取 root,不能正常使用了。想要 apk 可获得 root 权限,有两种方法:

  1. 关闭 SELinux 监控
  2. 配置 SELinux 权限

由于方案 2 需要熟悉复杂的 selinux 权限模型,而且我在实验过程中按网上办法硬是配置不上 domain(提示我没有设置 domain。有可能是因为我没有清空输出物,但不确定),所以我最后使用了方案 1。办法是在 $YOUR_AOSP/device/$YOUR_RAND/$YOUR_DEVICE/BoardConfig.mk 中的 BOARD_KERNEL_CMDLINE := xxxx下方加上:

BOARD_KERNEL_CMDLINE += androidboot.selinux=permissive

这样就可以使 SELinux 不阻止你的操作了,permissive 只会打日志不会做实际动作,disabled 是完全关闭。注意加上这个后会通过不了 Google 的 CTS 测试,如果你是厂家的话需要注意这一点,个人开发者不需要关心。

当然,启动完成后进入 shell,以 root 权限执行 setenforce 0 也是可以达到关闭 SELinux 监控的效果。但每次重启都要设置一遍,比较麻烦。

好了,关闭 SELinux 了。但此时你用 apk 尝试获取 root 权限,发现还是不行。因为 AOSP 的 su 是只能 shell 或者 root 用的。解决办法是:

  1. 注释掉 system/extras/su/su.c 中 main 的一行 "not allow" 的代码,这行代码会判断 uid。注释后重新 make 一次 su 就能正常使用了
  2. 使用非 AOSP 的 su,SuperSU 提供的 su 需要配合 SuperSU 其他文件,不能直接用。

然后我发现改了 su 还是不行。。我猜测 framework 层可能还有权限处理机制,那我再给 rom 集成 SuperSU 授权管理,这样总可以了把。当然你也可以每次刷 rom 后重新刷一遍第三方 recovery,再刷一遍 SuperSU。这个集成我搞了 2 天才完成,网上资料不多,而且没一个能用。。

这里提一点,如果不搞好 SELinux,集成了 SuperSU 也是没法用的。如果你不想使用方案 2,我提供几篇文章以供参考:

Compile Android 5.1.1 ROM with ROOT by SuperSU

这篇没有配置 init.rc 里面的 service 的 SELinux domain。反正我不行。

init 启动 Native Service 时出现Service xxxx needs a SELinux domain defined; please fix 警告的说明
[Android][L][SELinux]Define a SELinux domain for Service

这 2 篇教你如何配置 SELinux domain。我配置完了还是说我没配置:“init 启动 Native Service 时出现Service xxxx needs a SELinux domain defined; please fix”。上面我也提到了,可能我没 clean/clobber 才失败的,如果你尝试成功了,不妨也告诉我。

实现 SELinux | AOSP

这是 AOSP 官方对 SELinux 的介绍,在这个问题里我没看到更多的信息。

集成 SuperSU

上面这篇文章Compile Android 5.1.1 ROM with ROOT by SuperSU 也提到了集成 SuperSU 的步骤。可惜日月变迁,现在 SuperSU 已经不是单一个 su 运作了。通过翻看 SuperSU 的指南 How-To SU,我得到几个信息:

  1. 最少需要这 4 个文件,就可以保证 SuperSU 正常运行:
    /system/xbin/su
    /system/xbin/daemonsu
    /system/xbin/supolicy
    /system/lib(64)/libsupol.so
    
  2. 需要在开机时执行 daemonsu --auto-daemon,启动守护进程。

  3. 执行 daemonsu --auto-daemon 时会调用 supolicy ,然后调用 libsupol.so。用于配置 SuperSU 的 SELinux 权限。

通过翻看 SuperSU 的刷 recovery 的包里的 update-binary.sh 我得到几个信息:

  1. daemonsu 和 su 是同一个文件

  2. 开机执行 daemonsu --auto-daemon 的方法有好几种,如果有 /system/int/init.d/ 这个文件夹(我没有)就放一个脚本进去,不然就是劫持 /system/bin/app_process(64),或是给 /system/放一个 install-recovery.sh。原文 Furthermore, daemonsu --auto-daemon needs to be launched somehow on boot. This is generally done via install-recovery.sh, 99SuperSUDaemon, or hijacking app_process([32|64]).

最后这条信息告诉我们 SuperSU 不需要关闭 SELinux 也可以使用,也告诉我们集成 SELinux 而不关闭 SELinux 的办法。方法 1 由于我手机没有,所以不用;2 劫持 app_process 那个是把 app_process 链接给了 su,具体我没看懂;3 install-recovery.sh 这个文件是刷 recovery 的时候会产生的,当系统启动的时候就会执行到它,刷完就会删掉这个文件。SuperSU 利用了这个特性,在 install-recovery.sh 里执行了daemonsu --auto-daemon,而且这个文件一直存在。因为执行 install-recovery.sh 对应的是 flash_recovery 的 SELinux domain,是已经配置好的。SuperSU 通过这三种方法来绕过 SELinux,然后再通过 sepolicy 来修改 SELinux 配置。

而我这边因为一直都是配置在 init.rc 里,且关闭了 SELinux,所以没有用到上面提到的方案。

集成步骤(在 Compile Android 5.1.1 ROM with ROOT by SuperSU 基础上修改)

  1. 删除原 su。文件位置 system\extras\su,最简单的方法是把该目录下的 Android.mk 重命名或者删掉。

  2. 添加 SuperSU 相关文件。包括上面提到的 4个 Linux 文件,和一个 SuperSU.apk。Linux 文件我选择在 packages 下新建了一个 su,放入上面那4个文件,以及创建 Android.mk。我比较懒,就没有做架构选择,就只把自己的 Nexus 5 对应的 armv7 包里的文件拷过来了,suinit 和 sukernel 不需要,复制一份 su 改名为 daemonsu。Android.mk 内容如下:

    LOCAL_PATH := $(call my-dir)
    
    include $(CLEAR_VARS)
    
    LOCAL_MODULE_TAGS := optional
    LOCAL_MODULE := su
    LOCAL_SRC_FILES := $(LOCAL_MODULE)
    LOCAL_MODULE_CLASS := EXECUTABLES
    LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES)
    LOCAL_UNSTRIPPED_PATH := $(LOCAL_MODULE_PATH)
    include $(BUILD_PREBUILT)
    
    
    include $(CLEAR_VARS)
    
    LOCAL_MODULE_TAGS := optional
    LOCAL_MODULE := daemonsu
    LOCAL_SRC_FILES := $(LOCAL_MODULE)
    LOCAL_MODULE_CLASS := EXECUTABLES
    LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES)
    LOCAL_UNSTRIPPED_PATH := $(LOCAL_MODULE_PATH)
    include $(BUILD_PREBUILT)
    
    
    include $(CLEAR_VARS)
    
    LOCAL_MODULE_TAGS := optional
    LOCAL_MODULE := supolicy
    LOCAL_SRC_FILES := $(LOCAL_MODULE)
    LOCAL_MODULE_CLASS := EXECUTABLES
    LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES)
    LOCAL_UNSTRIPPED_PATH := $(LOCAL_MODULE_PATH)
    include $(BUILD_PREBUILT)
    
    
    include $(CLEAR_VARS)
    
    LOCAL_MODULE_TAGS := optional
    LOCAL_MODULE := libsupol.so
    LOCAL_MODULE_CLASS := SHARED_LIBRARIES
    LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)
    LOCAL_SRC_FILES := $(LOCAL_MODULE)
    OVERRIDE_BUILD_MODULE_PATH := $(TARGET_OUT_INTERMEDIATE_LIBRARIES)
    include $(BUILD_PREBUILT)
    

    apk 我放在了 packages/apps/SuperSU,同样的,放入 Superuser.apk(上面的官方刷机包里有),同时创建 Android.mk,内容如下:

    LOCAL_PATH := $(call my-dir)
    include $(CLEAR_VARS)
    
    LOCAL_MODULE := SuperSU
    
    LOCAL_SRC_FILES := Superuser.apk
    LOCAL_MODULE_CLASS := APPS
    LOCAL_MODULE_SUFFIX := $(COMMON_ANDROID_PACKAGE_SUFFIX)
    LOCAL_CERTIFICATE := PRESIGNED
    
    include $(BUILD_PREBUILT)
    
  3. 把第 2 步添加的 packages 添加到编译路径中。我只给 Nexus 5 设备添加了(这样不好,因为第一步把所有设备的 su 都删掉了)。修改 $YOUR_AOSP/device/$YOUR_RAND/$YOUR_DEVICE/device.mk,添加:
    PRODUCT_PACKAGES += \
         power.hammerhead
    
    +# SuperSU
    +#PRODUCT_PACKAGES += \
    +#    su \
    +#    daemonsu \
    +#    supolicy \
    +#    libsupol.so \
    +#    SuperSU
    
  4. 添加相关文件权限。修改 system/core/libcutils/fs_config.c,寻找 “system/xbin/su”,修改:
    -    { 04750, AID_ROOT,      AID_SHELL,     0, "system/xbin/su" },
    +    { 06755, AID_ROOT,      AID_ROOT,     0, "system/xbin/su" },
    +    { 07777, AID_ROOT,      AID_ROOT,     0, "system/xbin/daemonsu" },
    +    { 06755, AID_ROOT,      AID_ROOT,     0, "system/xbin/supolicy" },
    
  5. 在 system/core/rootdir/init.rc 中添加服务:
    service console /system/bin/sh
         class core
         console
         disabled
    -    user shell
    -    group shell log
    +    user root
    +    group root 
         seclabel u:r:shell:s0
    
    service installd /system/bin/installd
         class main
         socket installd stream 600 system system
    
    +# SuperSU
    +service daemonsu /system/xbin/daemonsu --auto-daemon &
    +    class main
    +    oneshot
    +
     service flash_recovery /system/bin/install-recovery.sh
         class main
         oneshot
    
  6. 编译,刷进去。自此 apk 可通过 SuperSU 获得 root 权限!

存在问题

由于对 AOSP 不熟悉,文件放置不太讲究,不能迎合多设备编译的需求。

还有一个小问题,就是点击 SuperSU 进入主界面时会提示有新 SU 可用,可是我已经下载最新版本了。我估计因为这是最小系统,SuperSU 发现有些文件缺失所以做出提示。

此时注意:不可以点击 INSTALL!因为点击 install SuperSU 会把 install-recovery.sh 加到文件系统里,而我本来又在 init.rc 里写过一次启动了,这会导致多次启动 daemonsu,结果是系统起不来(也可能是别的原因,但至少可以确定的是当我没有在 init.rc 配置启动 daemonsu,而是手动更新的时候,此时点击 INSTALL 系统是能正常启动的)。如果用到 SuperSU 提到的那三种办法,估计就不会多次启动了。因为平时也不需要打开 SuperSU,我就不深究下去了,毕竟编译花时间。

版权所有,转载请注明出处:
http://sickworm.com/?p=367

# # # # #