少女祈祷中...

前言

  • 看到隔壁用kernelsu(以下简称ksu)隐藏root的效果不错,但mix2s的4.9内核显然不在ksu的官方支持范围内,需要自编译内核。恰好我最近因为一位编译者的crdroid(以下简称为crd)内核只支持lzo的zram压缩算法(因为使用的lineageOS的设备树)。我需要更加高效的算法,比如lz4

编译环境准备

  • 本文以mix2s为主的配置,相当部分参考了Mix2s内核ksu编译action_Initsnow的源码。其他机型请参考Android内核编译教程_feichaixiaobai。使用的是lineageOS的内核源码。

  • 安装编译需要的相应包

    1
    2
    3
    4
    5
    6
    7
    sudo apt-get update

    sudo apt install bc bison build-essential ccache curl flex g++-multilib gcc-multilib git git-lfs gnupg gperf imagemagick lib32readline-dev lib32z1-dev libelf-dev liblz4-tool libsdl1.2-dev libssl-dev libxml2 libxml2-utils lzop pngcrush rsync schedtool squashfs-tools xsltproc zip zlib1g-dev

    wget https://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2_amd64.deb && sudo dpkg -i libtinfo5_6.3-2_amd64.deb && rm -f libtinfo5_6.3-2_amd64.deb

    wget https://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libncurses5_6.3-2_amd64.deb && sudo dpkg -i libncurses5_6.3-2_amd64.deb && rm -f libncurses5_6.3-2_amd64.deb
  • 安装交叉编译工具

    1
    2
    3
    4
    5
    6
    7
    8
    mkdir -p /home/runner
    cd /home/runner

    git clone https://github.com/LineageOS/android_prebuilts_gcc_linux-x86_aarch64_aarch64-linux-android-4.9.git --depth=1 gcc_aarch64

    git clone https://github.com/LineageOS/android_prebuilts_gcc_linux-x86_arm_arm-linux-androideabi-4.9.git --depth=1 gcc_arm

    git clone https://github.com/LineageOS/android_prebuilts_clang_kernel_linux-x86_clang-r416183b.git --depth=1 clang-r416183b
  • 拉取内核源码。这个地方是我修改了一部分的los的源码仓库,修改了fs/namespace.csecurity/selinux/hooks.c文件,以实现ksu模块的生效和卸载。

    1
    git clone https://github.com/wu1015/android_kernel_xiaomi_sdm845.git --depth=1

编译

  • 配置环境变量

    1
    2
    3
    cd /home/runner/android_kernel_xiaomi_sdm845

    PATH="/home/runner/clang-r416183b/bin:${PATH}"
  • 引入ksu源码(0.9.5)

    1
    curl -LSs "https://raw.githubusercontent.com/tiann/KernelSU/main/kernel/setup.sh" | bash -s b766b98513b5a7eb33bc1c4a76b5702bf1288f07
  • 合并编译配置文件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    cat ./arch/arm64/configs/vendor/xiaomi/mi845_defconfig > ./arch/arm64/configs/vendor/xiaomi/polaris_defconfig

    # 加入kprobe支持
    echo "CONFIG_KPROBES=y" >> ./arch/arm64/configs/vendor/xiaomi/polaris_defconfig
    echo "CONFIG_HAVE_KPROBES=y" >> ./arch/arm64/configs/vendor/xiaomi/polaris_defconfig
    echo "CONFIG_KPROBE_EVENTS=y" >> ./arch/arm64/configs/vendor/xiaomi/polaris_defconfig

    # 加入lz4内存压缩算法
    echo "CONFIG_CRYPTO_LZ4=y" >> ./arch/arm64/configs/vendor/xiaomi/polaris_defconfig
    echo "CONFIG_LZ4_COMPRESS=y" >> ./arch/arm64/configs/vendor/xiaomi/polaris_defconfig
    echo "CONFIG_LZ4_DECOMPRESS=y" >> ./arch/arm64/configs/vendor/xiaomi/polaris_defconfig

    cat ./arch/arm64/configs/vendor/xiaomi/polaris.config >> ./arch/arm64/configs/vendor/xiaomi/polaris_defconfig
  • 开始编译

    1
    2
    3
    make O=out ARCH=arm64 vendor/xiaomi/polaris_defconfig

    make -j$(nproc --all) O=out CC=clang ARCH=arm64 CLANG_TRIPLE=aarch64-linux-gnu- CROSS_COMPILE=/home/runner/gcc_aarch64/bin/aarch64-linux-android- CROSS_COMPILE_ARM32=/home/runner/gcc_arm/bin/arm-linux-androideabi- AR=llvm-ar NM=llvm-nm OBJCOPY=llvm-objcopy OBJDUMP=llvm-objdump STRIP=llvm-strip LLVM_IAS=1 LLVM=1
  • 使用AnyKernel3进行打包。完成后会在/home/runner/android_kernel_xiaomi_sdm845下产生一个AnyKernel3.zip文件,拿这个卡刷就行了。(注意准备好救砖工具,备份好boot分区)

    1
    2
    3
    4
    5
    6
    7
    git clone --recursive --depth=1 -j $(nproc) --branch polaris https://github.com/Shuery-Shuai/AnyKernel3.git AnyKernel3

    cp out/arch/arm64/boot/Image AnyKernel3/
    cp out/arch/arm64/boot/Image.gz AnyKernel3/
    cp out/arch/arm64/boot/Image.gz-dtb AnyKernel3/
    cd /home/runner/android_kernel_xiaomi_sdm845/AnyKernel3
    zip -r ../AnyKernel3.zip *

出现的bug以及解决方法

刷入模块没有效果

  • 具体表现为ksu内核编译正常,刷入有su权限,但是模块刷入重启后仍未灰色。解决方法见[参考文章](#[Bug修复指南]对于旧内核KernelSU不工作以及模块功能失效问题的部分解决方案 #956)。具体表现为security/selinux/hooks.c这个文件的修改。

步骤

  • 找到security/selinux/hooks.c文件,打开后找到static int check_nnp_nosuid这个函数。

  • 1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    static int check_nnp_nosuid(const struct linux_binprm *bprm,
    const struct task_security_struct *old_tsec,
    const struct task_security_struct *new_tsec)
    {
    int nnp = (bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS);
    int nosuid = (bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID);
    int rc;

    if (!nnp && !nosuid)
    return 0; /* neither NNP nor nosuid */

    if (new_tsec->sid == old_tsec->sid)
    return 0; /* No change in credentials */

    /*
    * The only transitions we permit under NNP or nosuid
    * are transitions to bounded SIDs, i.e. SIDs that are
  • 改为

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    static int check_nnp_nosuid(const struct linux_binprm *bprm,
    const struct task_security_struct *old_tsec,
    const struct task_security_struct *new_tsec)
    {
    static u32 ksu_sid;
    char *secdata;
    int nnp = (bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS);
    int nosuid = (bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID);
    int rc, error;
    u32 seclen;

    if (!nnp && !nosuid)
    return 0; /* neither NNP nor nosuid */

    if (new_tsec->sid == old_tsec->sid)
    return 0; /* No change in credentials */

    if (!ksu_sid)
    security_secctx_to_secid("u:r:su:s0", strlen("u:r:su:s0"), &ksu_sid);
    error = security_secid_to_secctx(old_tsec->sid, &secdata, &seclen);
    if (!error) {
    rc = strcmp("u:r:init:s0", secdata);
    security_release_secctx(secdata, seclen);
    if (rc == 0 && new_tsec->sid == ksu_sid)
    return 0;
    }
    /*
    * The only transitions we permit under NNP or nosuid
    * are transitions to bounded SIDs, i.e. SIDs that are
  • 改好保存重新编译。

ksu无法卸载模块

  • 解决方法见官方教程。具体表现为修改fs/namespace.c这个文件。步骤与上个类似,-为需要删除的行,+为需要添加的行。

编译好的内核

后记

  • 可能是我自己的问题,在crd上的隐藏效果一直一般,包括这次的ksu。而且因为mix2s内核老旧,一部分新的特性也无法体验到,确实还不一定有magisk好用。毕竟magisk拥有相当数量的模块可以使用,而ksu需要等别人适配(也许是越更新越不适配)。

参考文章和源码仓库