把模块打包进 magisk

boot_patch.sh
magisk 是这样把 magisk 添加到内核里的

"$SKIP64 add 0644 overlay.d/sbin/magisk64.xz magisk64.xz" \

所以直接在它的下面加上

"add 0644 overlay.d/sbin/hello.ko hello.ko" \

这样就能把 hello.ko 添加进内核里,在启动后,这个文件会在 magisk --path 路径下。至于怎么过去的,可以看看 magiskinit 的代码.

为了把 magiskboot 和 hello.ko 放到同一路径下 ( /data/user_de/0/com.topjohnwu.magisk/install ), 还需要修改一些代码
首先要把 hello.ko 放到 tools 目录下。然后修改代码
buildSrc/src/main/java/Setup.kt

val syncAssets = tasks.register("syncAssets", Sync::class.java){
.....
from(rootProject.file("tools")) {
            include("hello.ko") // 把/tools/hello.ko放到assets文件里
        }
.....
}

接下来这里
app/src/main/java/com/topjohnwu/magisk/core/tasks/MagiskInstaller.kt

private fun extractFiles(): Boolean {
    .......
    // Extract scripts
    for (script in listOf("util_functions.sh", "boot_patch.sh", "addon.d.sh","hello.ko")) {//从assets文件复制到install目录下,这样magiskboot就和hello.ko在同一目录下了
        val dest = File(installDir, script)
        context.assets.open(script).writeTo(dest)
    }
    ......
}

修改之后,再次编译,安装到内核,就可以看到 hello.ko 出现在 magisk --path 路径里.

zeus:/dev/C1VQ # ls
hello.ko  magisk  magisk32  magisk64  magiskpolicy  resetprop  su  supolicy

注入 init.rc

magisk 自带了注入 init.rc 的模板,在 native\jni\init\magiskrc.inc 里.
不过注入这个 rc 是不能执行 insmod 的。大家可以试一试.

需要注入 vendor 目录下的 rc 才行.
/vendor/etc/init/hw/init.qcom.rc 为例,注入方法类似注入 init.rc

native\jni\init\rootdir.cpp

void SARBase::patch_ro_root() {
    ......
    // Patch init.rc
    if (access(NEW_INITRC, F_OK) == 0) {
        // Android 11's new init.rc
        xmkdirs(dirname(ROOTOVL NEW_INITRC), 0755);
        patch_init_rc(NEW_INITRC, ROOTOVL NEW_INITRC, tmp_dir.data());
    } else {
        patch_init_rc("/init.rc", ROOTOVL "/init.rc", tmp_dir.data());
    }
    // patch /vendor/etc/init/hw/init.qcom.rc
    xmkdir(ROOTOVL "/vendor", 0755);
    xmkdir(ROOTOVL "/vendor/etc", 0755);
    xmkdir(ROOTOVL "/vendor/etc/init", 0755);
    xmkdir(ROOTOVL "/vendor/etc/init/hw", 0755);
    patch_vendor_init_rc("/vendor/etc/init/hw/init.qcom.rc",ROOTOVL "/vendor/etc/init/hw/init.qcom.rc",tmp_dir.data());
    ......
}
#include "magiskvendorc.inc"

static void patch_vendor_init_rc(const char *src, const char *dest, const char *tmp_dir) {
    FILE *rc = xfopen(dest, "we");
    if (!rc) {
        PLOGE("%s: open %s failed", __PRETTY_FUNCTION__, src);
        return;
    }
    file_readline(src, [=](string_view line) -> bool {
        // Else just write the line
        fprintf(rc, "%s", line.data());
        return true;
    });

    fprintf(rc, "\n");

    LOGD("Inject magisk vendor rc\n");
    fprintf(rc, MAGISK_VENDOR_RC, tmp_dir);

    fclose(rc);
    clone_attr(src, dest);
}

native\jni\init\magiskvendorc.inc

#include <magisk.hpp>
#include <selinux.hpp>

#define quote(s) #s
#define str(s) quote(s)

constexpr char MAGISK_VENDOR_RC[] =
"\n"
"on post-fs-data\n"
"    insmod %1$s/hello.ko\n" //直接载入magisk路径下的hello.ko
;

重新编译 magisk, 然后直接安装新的 magiskinit 到内核,重启

dmesg |grep hello.ko
[    4.200993] type=1400 audit(19253364.167:64): avc: denied { read } for comm="init" name="hello.ko" dev="tmpfs" ino=17 scontext=u:r:vendor_init:s0 tcontext=u:object_r:system_file:s0 tclass=file permissive=0

修改 sepolicy

看到上面的日志就可知需要修改 sepolicy, 其实在 magiskinit 里,已经有修改 sepolicy 的实现

native\jni\sepolicy\rules.cpp

void sepolicy::magisk_rules() {
    .......
    set_log_level_state(LogLevel::Warn, true);
    //添加vendor的sepolicy
    allow("vendor_init", "system_file", "file", "read");
    allow("vendor_init", "system_file", "file", "open");
    allow("vendor_init", "system_file", "system", "module_load");
}

这里简单说明下
allow 的四个参数分别代表被 sepolicy 拒绝的 scontext,tcontext,tclass,action
再编译,安装。重启.

dmesg |grep hello.ko
[    4.247766] hello_init
[    4.247767] hello_init
[    4.247769] hello_init
[    4.247771] hello_init
[    4.247773] hello_init
[    4.247774] hello_init
[    4.247776] hello_init
[    4.247778] hello_init
[    4.247779] hello_init
[    4.247781] hello_init
[    4.247783] hello_init
[    4.247784] hello_init
[    4.247786] hello_init
[    4.247788] hello_init
[    4.247789] hello_init
[    4.247791] hello_init
[    4.247793] hello_init
[    4.247795] hello_init
[    4.247796] hello_init
[    4.247798] hello_init
[    4.247800] hello_init
[    4.247801] hello_init

可以看到,驱动已经成功加载.

最后修改:2022 年 08 月 06 日
如果觉得我的文章对你有用,请随意赞赏