0%

Magisk内嵌驱动模块且启动加载

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") // 把/tools/hello.ko放到assets文件里
}
.....
}

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

1
2
3
4
5
6
7
8
9
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 路径里.

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() {
......
// 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());
......
}
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 {
// 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

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路径下的hello.ko
;

重新编译 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);
//添加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
再编译,安装。重启.

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

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