标签归档:AOSP

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

Published / by sickworm / 给 Android ROM(AOSP)集成 SuperSU 的方法有4条评论

本文实验配置:

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

下载 Android source code(AOSP)遇到的一些问题及解决方法

Published / by sickworm / 下载 Android source code(AOSP)遇到的一些问题及解决方法有1条评论

最近在搞 apk 爆破工程,经常需要调试别人的 apk,每次手动修改 apk 的 debuggable 属性比较麻烦,而且要有时候还不成功。所以还是一劳永逸,下载 AOSP ,把 ro.debuggable 打开,编一个 Nexus 5 的镜像给我手机用。关于 apk 调试的参考链接:https://www.0xaa55.com/technews/201602/00000215.html

建议使用清华镜像,免翻墙。教程链接:https://mirrors.tuna.tsinghua.edu.cn/help/AOSP/

下面是我在 windows 下,使用cygwin 下载官方 AOSP 时遇到的问题及解决办法:(在 windows 下载主要是为了方便我做别的事情,AOSP 官网上说 repo 只支持 linux 和 mac OS,cygwin 理论上也是支持的,但要填一些坑)

1. repo init 失败,request time out / 404

原因是没有翻墙。我使用的是 Proxifier + shadowsocks ,可以全局翻墙。 或者用普通的 VPN 也可以。网上方法是修改 repo 内容,增加 ss 翻墙配置的;也有修改镜像 url,改成国内的。我在 mac 上试过,部分链接还是被墙,没有成功。

2. 使用 cygwin 的 python 无法运行,报错 no module named site / no module named sysconfig / no module named fcntl;或者是 repo init 时 Get 完第一个之后没有预兆直接退出

这个问题可能是好几个原因造成的。首先,cygwin 是会继承 windows 的环境变量 PATH,所以 cygwin 可能会直接用你 windows 下配置的 python。这会带来几个问题:

  1. 直接输入 python 的 play ground 不能正常显示了(没研究具体原因)

  2. repo init 时提示 Get xxx.bundle 后直接退出。我跟了一下 repo 的代码,是 repo 构造 git clone 命令不对,其路径是 Windows 的路径,而不是 cygwin 的路径。

  3. 运行 repo init 时提示 no module named fcntl。上 google 查了一下,有回答说 Windows 没有 fcntl 这个 python 库。这个回答让我放弃了直接用 windows shell 运行 repo 的想法。(最后发现是存在的,不然 cygwin 也没办法运行 fcntl,因为 cygwin 不是 linux 虚拟机,本质也是 windows 的东西。因为网上说 Windows 没有 fcntl 放弃 windows shell,而尝试 cygwin 运行 repo,也是一个挺蠢的想法)

所以需要切换到 cygwin 的 python 。安装方法可以直接运行 cygwin 的 setup,搜索 python 下载。或使用 apt-cyg (需另外安装,网上有教程)执行 “`apt-cyg install python““。安装完成后还需要把 cygwin 的 $PATH 变量修改一下,把 windows 下的 python 路径剔除掉(我这里是 /cygdriver/d/Python27),否则还是会优先使用 Windows 下的 python。修改方法直接在 .bashrc 或 .bash_profile 下改就可以了。切换过来后,后还可能出现问题:

  1. 运行 python 报错 no module named site / no module named sysconfig

原因是 python 包路径错了,你可以输入 “import sys(回车)print sys.path “看一下。我这里就是莫名其妙多了当前目录的路径前缀。

解决办法是为cygwin 设置正确的路径,并写入环境变量 PYTHONPATH 中。我写的是/lib/python27.zip:/lib/python2.7:/lib/python2.7/plat-cygwin:/lib/python2.7/lib-tk:/lib/python2.7/lib-old:/lib/python2.7/lib-dynload

下面是我在 mac 下编译遇到的问题及解决办法:

首先官网上的环境准备要先做好,参考下面链接的 Setting up a Mac OS build environment 章节。防止意外,里面提到的 gmake 降级我都做了。
https://source.android.com/source/initializing

1. build/core/combo/mac_version.mk: Can not find SDK 10.6 at XXX

写这篇文章时 SDK 已经去到 10.12 了,而打开build/core/combo/mac_version.mk 一看,上面写着 supported versions 只支持 10.6 10.7 10.8 10.9。我直接在 supported version 上加了 10.12。结果遇到第二个问题。

2. desperate method XXXX

具体方法名字我忘了,说是 10.12 这个方法已经废弃了。那没办法,搜了一下 SDK 可以从网上下载。下载链接https://github.com/phracker/MacOSX-SDKs/releases

参考文章,教你如何放置 SDK 到正确路径:
http://www.jianshu.com/p/1513fc9e1a74

我看既然是找不到 10.6了,那就直接下 10.6 吧!结果出了第三个问题。

3. no member named llrintl / no member named llroundl

编译器说只有 lrintl 没有 llrintl。我跑去 MacOS SDK 里面看,有 llrintl,但是被宏控制着,因为其不是 C90 标准,需要加 -srd=c99 才可以。但要我找到调用编译的位置实在太麻烦了。

继续 google,有人说 10.11 10.9 都成功了,那我下一个 10.9放进去吧。结果还是提示找不到 10.6。

说好的 supported versions 呢?!我生气的吧 supported versions 中的 10.6 10.7 10.8 都删掉了,10.6 的 SDK 目录也删了,只留了一个 10.9。成功!

4. 切换分支时遇到:error.GitError: manifests rev-list (‘^HEAD’, ‘XXXXX’, ‘–‘): fatal: bad revision ‘^HEAD’

原因可能有好几个,我用了网上的方法都没有凑效。这个错误在我这里是 .git 的 HEAD 值丢失了,至于为什么我也不知道。这条语句的意思是:

在 manifests 这个 git 项目中执行 git rev-list ^HEAD XXXXX — 这个命令时,报错 fatal: bad revision ‘^HEAD’,即错误的版本 HEAD,意思是 HEAD 对应的 git 版本不正确。其中 manifests 这个工程在 .repo/manifests 中。 HEAD 对应的 git 版本存储在 .repo/manifests/.git/HEAD 中,这个 HEAD 文件的值为 ref: refs/heads/default。然后发现并没有 .repo/manifests/.git/heads/default 这个文件。解决办法:在其他目录重新 repo init 一次,把这个文件拷过来即可。

奇怪的是,我之前按照 http://blog.leanote.com/post/gyhlqq@gmail.com/Android-repo-sync-issue-fatal-bad-revision-HEAD-%E8%A7%A3%E5%86%B3%E6%96%B9%E6%A1%88 将整个 repo init 相关的文件都覆盖过去了,这个文件应该也复制过去才对,结果没有。

嗯。。我傻逼了,cp 命令的 src 为目录时,不是拷贝目录,而是把目录下的所有文件拷贝过去。还是推荐上面链接的做法,因为不止这一处会出问题,直接整个覆盖是最吼的。

版权所有,转载请注明出处:

http://sickworm.com/?p=346