## 设备信息
| 项目 | 值 |
|------|-----|
| 机型 | OnePlus 12 (PJD110, codename: waffle) |
| 系统 | LineageOS 23.2 Nightly (Android 16) |
| 内核 | 6.1.163-g44a24239336d (GKI) |
| 平台 | Snapdragon 8 Gen 3 (pineapple) |
| KernelSU | v3.2.4 |
| KMI | android14-6.1 |
## 问题描述
按照 KernelSU 官方文档,使用管理器 "选择并修补文件" 功能 patch init_boot.img,刷入后管理器仍然显示"未安装",KernelSU 完全没有生效。
## 排查过程
### 第一步:排除模块签名问题
最初怀疑是内核的模块签名保护导致加载失败,因为内核配置中:
```
CONFIG_MODULE_SIG=y
CONFIG_MODULE_SIG_PROTECT=y
```
但实际手动 `insmod` 测试后发现,报错并非签名相关。
### 第二步:定位真正原因 —— 符号缺失
在设备上手动尝试加载 `android14-6.1_kernelsu.ko`:
```bash
insmod /data/local/tmp/kernelsu.ko
```
dmesg 输出了大量 `Unknown symbol` 错误:
```
kernelsu: Unknown symbol avc_ss_reset (err -2)
kernelsu: Unknown symbol selnl_notify_policyload (err -2)
kernelsu: Unknown symbol selinux_status_update_policyload (err -2)
kernelsu: Unknown symbol symtab_search (err -2)
kernelsu: Unknown symbol change_pid (err -2)
...
```
进一步验证发现,这些符号在内核中**确实存在**,但**没有被导出(EXPORT_SYMBOL)**给模块使用:
```bash
# 符号存在于内核中(T = global text symbol)
cat /proc/kallsyms | grep avc_ss_reset
# ffffffe2705e3270 T avc_ss_reset
# 但 insmod 找不到它们,因为不在导出符号表中
```
**根因**:LineageOS 的内核虽然编译了 SELinux 相关功能,但没有将 KernelSU 所需的内部符号导出给可加载模块。这导致无论管理器怎么 patch,模块在开机时都无法加载。
### 第三步:排除使用预编译 GKI boot.img 的方案
KernelSU v1.x 曾提供预编译的 GKI boot.img(整体替换内核),但:
- v3.x 已不再提供 boot.img,只提供 `.ko` 模块文件
- v1.x 最新的 android14-6.1 boot.img 对应内核版本为 6.1.115,而 LineageOS 23.2 最新 nightly 集成的 GKI 内核已更新到 6.1.163(GKI 内核子版本随系统安全补丁持续升级,不同时期的 ROM 版本对应不同的子版本号)
- 由于 `modversions` 校验,vendor 模块的 vermagic (`6.1.163-g44a24239336d`) 与替换内核不匹配,会导致所有 vendor 驱动无法加载
## 解决方案:手动 patch init_boot.img
虽然标准的 `insmod` 路径因符号未导出而失败,但 KernelSU v3.x 的 `ksuinit` 并不依赖标准的模块加载机制。它作为 init 替身在内核启动最早期运行,通过**直接内核内存操作**注入 KernelSU,绕过了符号导出的限制。
管理器 patch 失败的原因尚不完全明确(可能是管理器的 KMI 自动检测或 magiskboot 版本问题),但**手动执行相同的 patch 流程**可以成功。
### 工具准备
- **magiskboot**:从 [magiskboot_build](a3fK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6m8b7$3S2W2M7q4)9J5c8X3#2S2k6$3W2K6K9$3u0G2L8%4c8Q4y4h3k6T1N6h3W2D9k6l9`.`.) 下载对应平台的 standalone 版本
- **ksuinit** 和 **android14-6.1_kernelsu.ko**:从 [KernelSU v3.2.4 Release](fa2K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6@1K9h3q4F1L8W2)9J5c8V1E0W2M7X3&6W2L8q4y4g2i4K6u0r3M7X3g2D9k6h3q4K6k6i4y4Q4x3V1k6@1j5h3N6Q4x3V1k6$3x3#2)9J5k6e0u0Q4x3X3f1@1) 下载
### 操作步骤
#### 1. 提取原始 init_boot
从你刷入的 ROM 包中解压提取 `init_boot.img`:
- **LineageOS**:下载对应版本的 zip 包(如 `lineage-23.2-20260409-nightly-waffle-signed.zip`),解压后在根目录找到 `init_boot.img`
- **官方 OTA**:从 OTA 全量包中提取对应的 `init_boot.img`
> 务必使用与当前系统版本完全一致的 init_boot.img。不同 nightly 版本的内核子版本可能不同,混用会导致问题。
>
> 注意:`adb root` + `dd` 提取分区的方式仅在 userdebug/eng 版本中可用,正式版本没有 adb root 权限。
#### 2. 解包 init_boot
```bash
magiskboot unpack init_boot_orig.img
```
会生成 `ramdisk.cpio` 等文件。
#### 3. 注入 KernelSU
```bash
# 准备文件:ksuinit 重命名为 init,kernelsu.ko 保持原名
cp ksuinit init
cp android14-6.1_kernelsu.ko kernelsu.ko
chmod 755 init kernelsu.ko
# 将原始 init 重命名为 init.real
magiskboot cpio ramdisk.cpio "mv init init.real"
# 注入 ksuinit 作为新的 init
magiskboot cpio ramdisk.cpio "add 0755 init init"
# 注入 kernelsu.ko
magiskboot cpio ramdisk.cpio "add 0755 kernelsu.ko kernelsu.ko"
```
#### 4. 重新打包
```bash
magiskboot repack init_boot_orig.img init_boot_patched.img
```
#### 5. 刷入
```bash
adb reboot bootloader
fastboot flash init_boot init_boot_patched.img
fastboot reboot
```
### 验证
重启后通过 dmesg 确认 KernelSU 已加载:
```bash
adb shell dmesg | grep KernelSU
```
看到以下关键日志即为成功:
```
KernelSU: Crowning manager: me.weishu.kernelsu(uid=10208)
KernelSU: allow root for: 10208
```
## 总结
| 方案 | 结果 | 原因 |
|------|------|------|
| 管理器 patch init_boot | 失败 | 管理器自动 patch 存在未知问题 |
| 标准 insmod 加载 .ko | 失败 | 内核未导出 SELinux 内部符号 |
| 预编译 GKI boot.img 替换内核 | 不可行 | 内核版本不匹配,vendor 模块会挂 |
| **手动 magiskboot patch init_boot** | **成功** | ksuinit 通过内存注入绕过符号限制 |
核心经验:KernelSU v3.x 的 `ksuinit` 不走标准模块加载路径,即使 `insmod` 报符号缺失也不代表 LKM 模式不可用。遇到管理器 patch 无效时,值得尝试手动 patch 排除管理器自身的问题。


[培训]《冰与火的战歌:Windows内核攻防实战》!从零到实战,融合AI与Windows内核攻防全技术栈,打造具备自动化能力的内核开发高手。