给 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 权限,有两种方法:
- 关闭 SELinux 监控
- 配置 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 用的。解决办法是:
- 注释掉
system/extras/su/su.c
中 main 的一行 "not allow" 的代码,这行代码会判断 uid。注释后重新 make 一次 su 就能正常使用了 - 使用非 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 才失败的,如果你尝试成功了,不妨也告诉我。
这是 AOSP 官方对 SELinux 的介绍,在这个问题里我没看到更多的信息。
集成 SuperSU
上面这篇文章Compile Android 5.1.1 ROM with ROOT by SuperSU 也提到了集成 SuperSU 的步骤。可惜日月变迁,现在 SuperSU 已经不是单一个 su 运作了。通过翻看 SuperSU 的指南 How-To SU,我得到几个信息:
- 最少需要这 4 个文件,就可以保证 SuperSU 正常运行:
/system/xbin/su /system/xbin/daemonsu /system/xbin/supolicy /system/lib(64)/libsupol.so
- 需要在开机时执行
daemonsu --auto-daemon
,启动守护进程。 -
执行
daemonsu --auto-daemon
时会调用 supolicy ,然后调用 libsupol.so。用于配置 SuperSU 的 SELinux 权限。
通过翻看 SuperSU 的刷 recovery 的包里的 update-binary.sh 我得到几个信息:
- daemonsu 和 su 是同一个文件
-
开机执行
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 基础上修改)
- 删除原 su。文件位置 system\extras\su,最简单的方法是把该目录下的 Android.mk 重命名或者删掉。
-
添加 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)
- 把第 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
- 添加相关文件权限。修改 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" },
- 在 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
- 编译,刷进去。自此 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