KernelSU 内核级 Root 方案解析:架构原理、Metamodule 模块系统与实战使用指南
【免费下载链接】KernelSUA Kernel based root solution for Android项目地址: https://gitcode.com/GitHub_Trending/ke/KernelSU
导读
KernelSU 是面向 Android GKI(Generic Kernel Image)设备的内核级 Root 解决方案,它运行在内核模式(kernel mode)中,直接在内核空间向用户态应用授予 Root 权限,而非像传统方案那样依赖用户态守护进程完成提权。本文以官方文档《Apa itu KernelSU?》(website/docs/id_ID/guide/what-is-kernelsu.md,英文版见 website/docs/guide/what-is-kernelsu.md)为骨架,结合本仓库的内核源码与 ksud 用户态实现,深入讲解 KernelSU 的"基于内核"设计哲学、可插拔的 Metamodule 模块管理体系,以及从安装、模块开发到自研 Metamodule 的完整实战路径。读完本文,你将理解 KernelSU 与 Magisk 类方案的本质差异,并掌握模块与 Metamodule 的安装、开发和调试方法。
什么是 KernelSU
KernelSU 是面向Android GKI 设备的 Root 解决方案,其核心特征是以内核为根基:它运行在内核模式中,并直接在内核空间向用户态应用授予 Root 权限。
这一设计可以从仓库源码中得到印证:kernel/core/init.c 是内核侧的初始化入口,kernelsu_init完成符号解析器(ksu_init_symbol_resolver)、系统调用 Hook(ksu_syscall_hook_init)、SELinux 钩子(ksu_lsm_hook_init)、Supercall 分发(ksu_supercalls_init)等一系列内核态组件的初始化;而 uapi/supercall.h 定义了内核与用户态之间的完整通信协议(UAPI),其中包含KSU_IOCTL_GRANT_ROOT、KSU_IOCTL_UID_GRANTED_ROOT、KSU_IOCTL_GET_APP_PROFILE等控制命令,可见"授权 Root"这一核心能力完全由内核态完成。
需要特别指出的是,KernelSU 的定位是GKI 设备。GKI(Generic Kernel Image)是 Google 推行的通用内核镜像规范,其 Kernel Module Interface(KMI)机制保证了相同 KMI 的内核镜像可以互换使用,这也正是 KernelSU 能够以内核补丁 / LKM(Loadable Kernel Module)形式分发的前提。关于设备兼容性的详细判断方法,见安装指南。
核心特性:基于内核的能力
KernelSU 最主要的特点就是基于内核(kernel-based)。由于它工作在内核模式,因此能够提供以往 Root 方案无法提供的内核级接口,官方文档列举了三类典型能力:
- 硬件断点:可以在内核模式中为任意进程添加硬件断点(hardware breakpoint);
- 物理内存访问:可以无感知地访问任意进程的物理内存;
- 系统调用拦截:可以在内核空间拦截任意 syscall。
这些能力在仓库的 Hook 子系统中都有对应的实现载体。例如 kernel/hook/syscall_hook.c 与 kernel/hook/syscall_hook_manager.c 实现系统调用级别的拦截管理,kernel/hook/lsm_hook.c 挂接 Linux Security Module 钩子,kernel/hook/patch_memory.h 及 arch 目录下的 arm64/patch_memory.c、x86_64/patch_memory.c 则提供架构相关的内存补丁能力。内核启动流程中还通过kprobe之外的多种机制配合完成运行时 Hook(相关初始化见 kernel/core/init.c)。
从源码结构看,KernelSU 的内核侧能力还可以进一步细分为:
| 能力域 | 代表文件 | 说明 |
|---|---|---|
| Root 授权与白名单 | kernel/policy/allowlist.c、kernel/policy/app_profile.c | 维护允许获取 Root 的应用列表与应用级 Profile |
| SELinux 策略注入 | kernel/selinux/sepolicy.c、kernel/selinux/rules.c | 在内核中动态加载/注入 sepolicy 规则 |
| 隐藏与反检测 | kernel/feature/selinux_hide.c、kernel/feature/kernel_umount.c | SELinux 状态隐藏、内核态 umount 管理 |
| 系统调用拦截 | kernel/hook/syscall_event_bridge.c | 将 syscall 事件桥接给用户态处理 |
| Supercall 分发 | kernel/supercall/dispatch.c、kernel/supercall/supercall.c | 处理来自用户态的超级调用请求 |
这些模块共同构成了"内核空间直接授权 + 内核级 Hook"的技术底座,这也是官方文档强调"提供了我们以前从未拥有过的内核接口"的底气所在。
Metamodule 模块系统:可插拔的挂载架构
在基于内核的能力之外,KernelSU 还提供了一套Metamodule(元模块)系统——一种用于模块管理的可插拔架构。与把挂载逻辑写死在核心中的传统 Root 方案不同,KernelSU 将模块的安装与挂载职责委派给 Metamodule,从而允许用户安装meta-overlayfs之类的 Metamodule,为/system等分区提供 systemless(无系统级修改)能力。
什么是 Metamodule
Metamodule 是一种特殊类型的 KernelSU 模块,它为模块系统提供核心基础设施功能。普通模块修改的是系统文件,而 Metamodule 控制的是普通模块"如何"被安装和挂载。其关键特征包括:
- 基础设施角色:为普通模块提供其依赖的服务;
- 单实例约束:同一时间只能安装一个 Metamodule;
- 优先执行:Metamodule 脚本先于普通模块脚本运行;
- 专用钩子:提供安装(
metainstall.sh)、挂载(metamount.sh)、清理(metauninstall.sh)三个 Hook 脚本。
这些特征在用户态实现中有清晰的代码对应:userspace/ksud是 KernelSU 的用户态守护进程,其中 userspace/ksud/src/metamodule.rs 完整承载了 Metamodule 的识别、路径解析、symlink 维护与脚本执行逻辑;脚本名称常量定义在 userspace/ksud/src/defs.rs,包括metamount.sh、metainstall.sh、metauninstall.sh。
为什么需要 Metamodule
传统 Root 方案把挂载逻辑内建于核心中,导致两个问题:更容易被检测(核心直接执行挂载,暴露检测面),更难以演进(任何挂载逻辑的变更都依赖核心更新)。KernelSU 的 Metamodule 架构通过关注点分离解决了这些问题:
- 降低检测面:KernelSU 自身不执行挂载,减少了可被检测的向量;
- 稳定性:核心守护进程保持稳定,挂载实现可以独立演进;
- 可创新:社区无需 fork KernelSU 即可开发替代挂载策略;
- 可选择:用户可挑选最适合自己需求的实现。
挂载策略也因此变得多样化:可以完全不挂载(仅使用无需挂载的模块)、使用OverlayFS 挂载(通过meta-overlayfs,支持读写层)、使用Magic mount(Magisk 兼容挂载,应用兼容性更好),甚至实现FUSE 覆盖层、自定义 VFS 挂载等全新方案。更进一步,Metamodule 的机制不止于挂载——它还能以不修改 KernelSU 核心的方式扩展内核模块支持等新特性,并允许独立于 KernelSU 版本更新实现。
需要特别警惕的是官方文档中的一条警告:如果没有安装任何 Metamodule,模块将不会被挂载。全新安装的 KernelSU 必须先安装一个 Metamodule(如meta-overlayfs),模块功能才能生效。这与 userspace/ksud/src/metamodule.rs 中exec_mount_script的逻辑一致:只有当存在且未被禁用的 Metamodule 提供metamount.sh时,挂载脚本才会被执行。
用户视角:Metamodule 的安装、检查与卸载
安装 Metamodule
Metamodule 的安装方式与普通模块完全相同:
- 下载 Metamodule 的 ZIP 文件(例如
meta-overlayfs.zip); - 打开 KernelSU Manager 应用;
- 点击浮动操作按钮(➕);
- 选择 Metamodule 的 ZIP 文件;
- 重启设备。
官方参考实现meta-overlayfs提供了基于 overlayfs 的传统模块挂载,并支持 ext4 镜像。
检查当前 Metamodule
在 KernelSU Manager 应用的"模块"页面可以看到当前激活的 Metamodule,它会以特殊标识显示在模块列表中。在命令行层面,ksud 通过检查/data/adb/metamodule符号链接(指向/data/adb/modules/<metamodule_id>)来定位激活的 Metamodule,若链接失效则会回退扫描所有模块的module.prop中是否存在metamodule=1标记(见 userspace/ksud/src/metamodule.rs)。
卸载与切换 Metamodule
::: danger 高危警告 卸载 Metamodule 将影响所有模块:卸载后,模块将不再被挂载,直到安装新的 Metamodule。 :::
卸载步骤:
- 打开 KernelSU Manager;
- 在模块列表中找到 Metamodule;
- 点击卸载(此时会看到特殊警告提示);
- 确认操作;
- 重启设备。
由于同一时间只能安装一个 Metamodule(ksud 会阻止第二个 Metamodule 的安装以避免冲突),切换 Metamodule 需要按以下顺序操作:
- 卸载所有普通模块;
- 卸载当前 Metamodule;
- 重启;
- 安装新的 Metamodule;
- 重新安装普通模块;
- 再次重启。
是否需要 Metamodule
- 普通用户:仅当想使用需要挂载的模块时才需要;如果只用那些仅运行脚本、不修改系统文件的模块,则无需 Metamodule;
- 模块开发者:不需要,正常开发模块即可;只有当模块需要挂载时,用户才需要安装提供挂载能力的 Metamodule;
- 进阶用户:只有当你想定制挂载行为或开发替代挂载实现时才需要。
开发者视角:自研 Metamodule
基础要求:module.prop 标记
Metamodule 通过在module.prop中声明特殊属性来标识自身:
id=meta-example name=My Custom Metamodule version=1.0 versionCode=1 author=Your Name description=Custom module mounting implementation metamodule=1其中metamodule=1(或metamodule=true)是关键标记,没有该属性的模块会被当作普通模块处理。ksud 的判定逻辑见 userspace/ksud/src/metamodule.rs:读取metamodule字段并判断其值是否为"1"或"true"(不区分大小写)。此外官方强烈建议 Metamodule 的 ID 以meta-前缀命名(如meta-overlayfs、meta-magicmount),便于用户识别并避免与普通模块冲突。
文件结构
一个 Metamodule 的典型目录结构如下:
meta-example/ ├── module.prop (必须包含 metamodule=1) │ │ *** Metamodule 专用钩子 *** ├── metamount.sh (可选:自定义挂载处理器) ├── metainstall.sh (可选:普通模块的安装钩子) ├── metauninstall.sh (可选:普通模块的清理钩子) │ │ *** 标准模块文件(均可选)*** ├── customize.sh (安装定制脚本) ├── post-fs-data.sh (post-fs-data 阶段脚本) ├── service.sh (late_start service 脚本) ├── boot-completed.sh (开机完成脚本) ├── uninstall.sh (Metamodule 自身的卸载脚本) └── [任意附加文件]Metamodule 除了三个专用钩子外,同样可以使用全部标准模块特性(生命周期脚本等)。
三个 Hook 脚本
1. metamount.sh —— 挂载处理器
- 作用:控制模块在开机过程中的挂载方式;
- 执行时机:
post-fs-data阶段,位于所有模块脚本之前; - 环境变量:
MODDIR(Metamodule 目录路径,如/data/adb/modules/meta-example)以及所有标准 KernelSU 环境变量; - 职责:systemless 挂载所有已启用模块、检查
skip_mount标志、处理模块的特殊挂载需求。
::: danger 关键要求 执行挂载操作时,必须将源(source/device)名称设置为"KSU",以标识挂载归属于 KernelSU。传统 mount 命令示例:
mount -t overlay -o lowerdir=/lower,upperdir=/upper,workdir=/work KSU /target现代 mount API 则需设置源字符串:
fsconfig_set_string(fs, "source", "KSU")?;这是内核卸载(kernel umount)与 zygisk 卸载(zygisksu umount)能正确识别并卸载这些挂载的前提。 :::
一个简单的 bind mount 实现示例:
#!/system/bin/sh MODDIR="${0%/*}" # 示例:简单的 bind mount 实现 for module in /data/adb/modules/*; do if [ -f "$module/disable" ] || [ -f "$module/skip_mount" ]; then continue fi if [ -d "$module/system" ]; then # 以 source=KSU 挂载(必须!) mount -o bind,dev=KSU "$module/system" /system fi done2. metainstall.sh —— 安装钩子
- 作用:定制普通模块的安装流程;
- 执行时机:模块安装过程中,文件解压完成后、安装结束前。该脚本由内置安装器source(引入执行),工作方式类似
customize.sh; - 环境变量与函数:继承内置
install.sh的全部变量与函数,包括变量MODPATH、TMPDIR、ZIPFILE、ARCH、API、IS64BIT、KSU、KSU_VER、KSU_VER_CODE、KSU_UAPI_VER、KSU_RUNTIME_MODE、KSU_LATE_LOAD、BOOTMODE等,以及函数:ui_print <msg>—— 向控制台打印消息;abort <msg>—— 打印错误并终止安装;set_perm <target> <owner> <group> <permission> [context]—— 设置文件权限;set_perm_recursive <directory> <owner> <group> <dirpermission> <filepermission> [context]—— 递归设置权限;install_module—— 调用内置模块安装流程。
典型用途包括:在内置安装前后处理模块文件(准备好后调用install_module)、移动模块文件、校验模块兼容性、建立特殊目录结构、初始化模块专属资源等。注意:安装 Metamodule 自身时不会调用该脚本。ksud 中get_install_script的实现在安装普通模块时优先拼接 Metamodule 提供的metainstall.sh,而安装 Metamodule 本身时始终使用默认安装器(见 userspace/ksud/src/metamodule.rs)。
3. metauninstall.sh —— 清理钩子
- 作用:普通模块被卸载时清理相关资源;
- 执行时机:模块卸载过程中、模块目录被删除之前;
- 环境变量:
MODULE_ID(被卸载模块的 ID)。
典型用途:处理文件、清理符号链接、释放已分配资源、更新内部跟踪状态。示例:
#!/system/bin/sh # 卸载普通模块时被调用 MODULE_ID="$1" IMG_MNT="/data/adb/metamodule/mnt" # 从镜像中移除模块文件 if [ -d "$IMG_MNT/$MODULE_ID" ]; then rm -rf "$IMG_MNT/$MODULE_ID" fiksud 通过exec_metauninstall_script在卸载模块时以MODULE_ID环境变量调用该脚本(见 userspace/ksud/src/metamodule.rs)。
开机执行顺序
理解开机执行顺序对 Metamodule 开发至关重要:
post-fs-data 阶段: 1. 公共 post-fs-data.d 脚本执行 2. 修剪模块、restorecon、加载 sepolicy.rule 3. Metamodule 的 post-fs-data.sh 执行(若存在) 4. 普通模块的 post-fs-data.sh 执行 5. 加载 system.prop 6. Metamodule 的 metamount.sh 执行 └─> 以 systemless 方式挂载所有模块 7. post-mount.d 阶段运行 - 公共 post-mount.d 脚本 - Metamodule 的 post-mount.sh(若存在) - 普通模块的 post-mount.sh service 阶段: 1. 公共 service.d 脚本执行 2. Metamodule 的 service.sh 执行(若存在) 3. 普通模块的 service.sh 执行 boot-completed 阶段: 1. 公共 boot-completed.d 脚本执行 2. Metamodule 的 boot-completed.sh 执行(若存在) 3. 普通模块的 boot-completed.sh 执行关键要点:
metamount.sh在所有post-fs-data 脚本(包括 Metamodule 与普通模块的)之后运行;- Metamodule 的生命周期脚本(
post-fs-data.sh、service.sh、boot-completed.sh)始终先于普通模块脚本运行; .d目录中的公共脚本先于 Metamodule 脚本运行;post-mount阶段在挂载完成后运行。
这一顺序在 ksud 中由exec_stage_script(按阶段执行{stage}.sh)与exec_mount_script(执行metamount.sh)配合实现,且脚本通过 busybox 的sh解释器以阻塞方式执行(见 userspace/ksud/src/metamodule.rs)。
符号链接机制
Metamodule 安装后,KernelSU 会创建符号链接:
/data/adb/metamodule -> /data/adb/modules/<metamodule_id>这为访问激活的 Metamodule 提供了与 ID 无关的稳定路径,便于一致性访问、快速检测激活状态与简化配置。ksud 中的ensure_symlink/remove_symlink负责创建与移除该链接(见 userspace/ksud/src/metamodule.rs),目录常量METAMODULE_DIR定义为/data/adb/metamodule/(见 userspace/ksud/src/defs.rs)。
真实案例:meta-overlayfs
meta-overlayfs是官方参考实现,展示了 Metamodule 开发的最佳实践:
双目录架构:
- 元数据目录
/data/adb/modules/:存放module.prop、disable、skip_mount标记,开机扫描快、存储占用小; - 内容目录
/data/adb/metamodule/mnt/:存放模块的实际文件(system、vendor、product 等),保存在 ext4 镜像modules.img中,利用 ext4 特性优化空间。
metamount.sh 实现:
#!/system/bin/sh MODDIR="${0%/*}" IMG_FILE="$MODDIR/modules.img" MNT_DIR="$MODDIR/mnt" # 若未挂载则挂载 ext4 镜像 if ! mountpoint -q "$MNT_DIR"; then mkdir -p "$MNT_DIR" mount -t ext4 -o loop,rw,noatime "$IMG_FILE" "$MNT_DIR" fi # 设置双目录支持的环境变量 export MODULE_METADATA_DIR="/data/adb/modules" export MODULE_CONTENT_DIR="$MNT_DIR" # 执行挂载二进制 # (实际挂载逻辑在 Rust 二进制中) "$MODDIR/meta-overlayfs"关键特性:
- 使用内核 overlayfs 实现真正的 systemless 修改;
- 支持多个分区:system、vendor、product、system_ext、odm、oem;
- 通过
/data/adb/modules/.rw/提供读写层支持; - 所有 overlay 挂载通过
fsconfig_set_string(fs, "source", "KSU")设置dev=KSU,保证正确识别。
开发与测试最佳实践
开发时:
- 始终将挂载源设置为
"KSU"—— 内核 umount 与 zygisksu umount 依赖它正确卸载; - 优雅处理错误—— 开机流程对时间敏感;
- 尊重标准标志—— 支持
skip_mount与disable; - 记录操作日志—— 使用
echo或日志便于调试; - 充分测试—— 挂载错误可能导致开机循环(boot loop);
- 文档化行为—— 清楚说明 Metamodule 的职责;
- 提供迁移路径—— 帮助用户从其他方案切换。
发布前测试清单:
- 在干净的 KernelSU 环境上测试安装;
- 用多种类型的模块验证挂载;
- 检查与常见模块的兼容性;
- 测试卸载与清理流程;
- 验证开机性能(注意
metamount.sh是阻塞执行的!); - 确保错误处理得当,避免开机循环。
常见问题
- 能否同时安装多个 Metamodule?不能,同一时间只能安装一个,以防止冲突并保证行为可预测。
- 卸载唯一的 Metamodule 会发生什么?模块将不再被挂载;设备仍能正常开机,但模块修改不会生效,直到安装新的 Metamodule。
meta-overlayfs是必须的吗?不是。它提供与大多数模块兼容的标准 overlayfs 挂载;如有不同需求,可以自研 Metamodule。
如何安装与使用 KernelSU
详细安装步骤请参阅安装指南。这里提炼几个关键前提:
- 确认设备支持:安装 KernelSU Manager 后,若显示
Unsupported,说明需要自行编译内核(KernelSU 不会为设备提供现成 boot.img);若显示Not installed,则设备受官方支持; - 备份原厂 boot.img:刷写前务必备份,遇到 boot loop 时可通过 fastboot 刷回原厂镜像恢复;
- 理解 KMI(Kernel Module Interface):相同 KMI 的内核互相兼容,KMI 不同会导致无法启动。GKI 内核版本格式为
Version.PatchLevel.SubLevel-AndroidRelease-KmiGeneration-suffix,其中 SubLevel 不属于 KMI 的一部分; - 注意安全补丁级别(Security Patch Level):较新的设备可能有防回滚机制,刷入安全补丁级别过旧的内核镜像可能导致 boot loop;
- 区分内核版本与 Android 版本:内核版本与 Android 系统版本并不必然一致,刷写前务必以内核版本为准。
安装完成后,普通模块的使用方式与传统方案基本一致(模块开发详见模块指南,与 Magisk 的详细对比见与 Magisk 的差异)。
如何构建 KernelSU
关于从源码构建 KernelSU,仓库提供了完整的构建支撑材料:
- 内核侧:kernel/Makefile、kernel/Kconfig、kernel/Kbuild 定义了内核模块的构建规则与配置项,kernel/setup.sh 提供环境准备脚本;
- 用户态:ksud 守护进程基于 Rust 构建,其依赖清单见 userspace/ksud/Cargo.toml,ksuinit 见 userspace/ksuinit/Cargo.toml;
- 构建辅助:justfile 提供了常用的任务编排命令;
- 总体说明可参考仓库根目录的 docs/README.md。
从源码结构可以推断,构建流程大致涉及:准备与目标设备 KMI 匹配的内核源码树 → 集成 KernelSU 内核侧代码(或编译为 LKM)→ 编译 ksud/ksuinit 用户态组件 → 打包刷写镜像。由于 KernelSU 只对 GKI 设备提供官方支持,非 GKI 设备的集成方式可参考非 GKI 设备集成指南。
讨论与社区
KernelSU 项目维护有 Telegram 官方群组(@KernelSU),供用户交流使用与开发问题。对本仓库感兴趣的开发者,也可以通过阅读 kernel/core/init.c(内核初始化)、userspace/ksud/src/metamodule.rs(Metamodule 实现)、uapi/supercall.h(UAPI 协议)等源码,深入理解其内核级 Root 与可插拔模块架构的实现细节。
总结
KernelSU 通过"内核空间直接授权"确立了不同于传统 Root 方案的技术路线,并以 Metamodule 架构把模块挂载能力从核心中解耦出来——前者提供了硬件断点、物理内存访问、syscall 拦截等前所未有的内核级接口,后者则在降低检测面、保持核心稳定的同时,为模块生态开辟了 OverlayFS、Magic mount、FUSE 乃至完全自定义挂载策略的演进空间。对于开发者而言,理解module.prop的metamodule=1标记、三个专用 Hook 脚本(metamount.sh/metainstall.sh/metauninstall.sh)以及开机执行顺序,是进入 Metamodule 开发的关键一步;而无论用户还是开发者,都应牢记一条铁律:没有 Metamodule,模块就不会被挂载。
【免费下载链接】KernelSUA Kernel based root solution for Android项目地址: https://gitcode.com/GitHub_Trending/ke/KernelSU
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考