Magisk 内嵌驱动模块且开机启动加载.
把模块打包进 magisk
在 boot_patch.sh
里
magisk 是这样把 magisk 添加到内核里的
1
| "$SKIP64 add 0644 overlay.d/sbin/magisk64.xz magisk64.xz" \
|
所以直接在它的下面加上
1
| "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
1 2 3 4 5 6 7
| val syncAssets = tasks.register("syncAssets", Sync::class.java){ ..... from(rootProject.file("tools")) { include("hello.ko") } ..... }
|
接下来这里
app/src/main/java/com/topjohnwu/magisk/core/tasks/MagiskInstaller.kt
1 2 3 4 5 6 7 8 9
| private fun extractFiles(): Boolean { ....... for (script in listOf("util_functions.sh", "boot_patch.sh", "addon.d.sh","hello.ko")) { val dest = File(installDir, script) context.assets.open(script).writeTo(dest) } ...... }
|
修改之后,再次编译,安装到内核,就可以看到 hello.ko 出现在 magisk --path
路径里.
1 2
| 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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| void SARBase::patch_ro_root() { ...... if (access(NEW_INITRC, F_OK) == 0) { 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()); } 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()); ...... }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| #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 { 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
1 2 3 4 5 6 7 8 9 10 11
| #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, 然后直接安装新的 magiskinit 到内核,重启
1 2
| 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
1 2 3 4 5 6 7 8
| void sepolicy::magisk_rules() { ....... set_log_level_state(LogLevel::Warn, true); 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
再编译,安装。重启.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| 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
|
可以看到,驱动已经成功加载.