KernelSU 隐藏功能解析:利用.ksurc定制 su 会话的 Shell 初始化环境
【免费下载链接】KernelSUA Kernel based root solution for Android项目地址: https://gitcode.com/GitHub_Trending/ke/KernelSU
本文基于 website/docs/ja_JP/guide/hidden-features.md(英文原版见 website/docs/guide/hidden-features.md)展开。KernelSU 是一款基于内核的 Android root 方案,其 ksud 用户态守护进程与 su 实现共同支撑起一套完整的 root 会话体系。
.ksurc正是这套体系中一个常被忽略、却非常实用的"隐藏功能":它允许用户为 su 会话注入自定义的 Shell 初始化脚本,让每一次 root 会话自动携带自己的环境变量、别名与函数定义。读完本文,你将理解.ksurc的加载时机、它与 Android 默认mkshrc的关系、其底层实现路径,以及如何安全地配置和使用它。
背景:Android 的sh与mkshrc加载机制
在 Android 系统中,/system/bin/sh并不是 GNU Bash,而是mksh(MirBSD Korn Shell)。mksh 在作为**登录 Shell(login shell)**启动时,会读取环境变量ENV所指向的文件作为其初始化脚本(rc 文件)。
默认情况下,Android 将ENV指向/system/etc/mkshrc,因此每次以登录方式进入 Android 的 shell 会话时,系统都会加载这个全局 rc 文件,其中定义了PS1提示符、LS_COLORS等基础环境。
KernelSU 的.ksurc机制正是对这一行为的接管:当用户创建/data/adb/ksu/.ksurc文件后,su 会话将优先加载这份自定义 rc 文件,而不是默认的/system/etc/mkshrc。这样,用户可以在不修改系统分区的前提下,为 root 会话定制一套完全属于自己的 Shell 初始化逻辑。
核心配置:.ksurc文件
原文档给出的配置非常简洁,却直指核心:
默认情况下
/system/bin/sh会读取/system/etc/mkshrc。 通过创建/data/adb/ksu/.ksurc文件,可以让 su 加载自定义的 rc 文件。
结合源码可以确认,.ksurc的完整路径定义位于 userspace/ksud/src/defs.rs:
pub const ADB_DIR: &str = "/data/adb/"; pub const WORKING_DIR: &str = concatcp!(ADB_DIR, "ksu/"); pub const KSURC_PATH: &str = concatcp!(WORKING_DIR, ".ksurc"); // /data/adb/ksu/.ksurc即完整路径为/data/adb/ksu/.ksurc。该目录同时也是 ksud 守护进程的工作目录(WORKING_DIR),存放 bin、lib、log、profile 等子目录。
创建与使用
在支持 root 的 shell 中执行:
# 创建自定义 rc 文件 cat > /data/adb/ksu/.ksurc <<'EOF' # 自定义提示符 export PS1='[root@kernelSU] \$ ' # 常用别名 alias ll='ls -lA' alias grep='grep --color=auto' # 自定义函数 ksuinfo() { uname -a getprop ro.build.version.release } EOF # 赋予合适的权限(ksu 工作目录通常为 root 所有) chown root:root /data/adb/ksu/.ksurc chmod 644 /data/adb/ksu/.ksurc创建后,下一次进入 su root 会话时,上述PS1、ll别名与ksuinfo函数便会自动生效。
与/system/etc/mkshrc的关系
需要注意,.ksurc是替代而非叠加默认mkshrc的机制——一旦存在.ksurc,su 会话将把ENV指向它,默认的/system/etc/mkshrc不再被加载(详见下文实现原理)。因此如果你依赖mkshrc中的既有定义(如LS_COLORS),应在.ksurc中自行补齐,或通过source /system/etc/mkshrc显式引入:
# 在 .ksurc 开头显式加载系统默认 rc,再叠加自定义内容 if [ -r /system/etc/mkshrc ]; then . /system/etc/mkshrc fi实现原理一:su路径中的ENV注入
su命令的实际实现位于 userspace/ksud/src/su.rs。其中root_shell()函数负责构造并执行目标 shell,在参数解析完成后、执行 shell 之前,有一段专门处理.ksurc的逻辑(su.rs):
// when KSURC_PATH exists and ENV is not set, set ENV to KSURC_PATH if PathBuf::from(defs::KSURC_PATH).exists() && env::var("ENV").is_err() { command.env("ENV", defs::KSURC_PATH); }这段代码揭示了两个关键行为:
- 存在性判断:只有
KSURC_PATH(即/data/adb/ksu/.ksurc)实际存在时才会注入; - 不覆盖已有
ENV:如果调用环境中已经设置了ENV变量,则保持原样,不会强制替换——这保证了用户主动指定的 rc 文件优先级更高,也避免了与外部传入的环境变量冲突。
此外,从同文件的参数解析逻辑可以看到su对 shell 的选择与登录语义(su.rs):
let shell = matches .opt_str("s") .unwrap_or_else(|| "/system/bin/sh".to_string()); // ... // if the first free argument is "-", treat as login shell if !matches.free.is_empty() && matches.free[free_idx] == "-" { is_login = true; free_idx += 1; } // ... let arg0 = if is_login { "-" } else { executable };也就是说:
- 默认 shell 是
/system/bin/sh,可用su -s SHELL指定其他 shell; - 当以登录 shell(
su -)方式进入时,mksh 才会按ENV机制加载 rc 文件; -p/--preserve-environment会保留整个环境,此时调用方若自带ENV,.ksurc的注入同样会被让位。
同一函数还在启动 shell 前将/data/adb/ksu/bin追加进PATH(su.rs),确保 ksud 配套的二进制工具在 root 会话中可直接调用。
实现原理二:adb root路径中的execle钩子
.ksurc不仅作用于su命令,还覆盖了ADB root场景。KernelSU 的 ADB Root 功能通过注入libadbroot.so实现(见 adbroot.cc),其中拦截了execle系统调用,在 adb shell 进程被替换为sh时,动态改写环境变量(adbroot.cc):
// If the user creates ksurc, use ksurc instead of mkshrc bool ksurc_exists = (access("/data/adb/ksu/.ksurc", F_OK) == 0); const char *ksu_env_str = "ENV=/data/adb/ksu/.ksurc"; if (old_envp != nullptr) { for (size_t i = 0; old_envp[i] != nullptr; ++i) { // skip original ENV in envp // even there shouldn't exists in normal android, but let's still check it, // avoid newer android/custom rom modify there if (ksurc_exists && strncmp(old_envp[i], "ENV=", 4) == 0) { continue; } env_list.push_back(old_envp[i]); } } if (ksurc_exists) { // push our ENV in here!!! env_list.push_back(ksu_env_str); }这段实现说明:
- 当
/data/adb/ksu/.ksurc存在时,execle钩子会剔除原有ENV=条目(防御性地兼容新版 Android 或定制 ROM 可能自带ENV的情况),再注入ENV=/data/adb/ksu/.ksurc; - 因此通过
adb root获得的 root shell 同样会加载.ksurc,行为与su会话保持一致。
代码注释还引用了 AOSP 中packages/modules/adb/daemon/shell_service.cpp的相关逻辑(L389-394),说明此机制是对 Android adb shell 服务原生行为的对齐与接管。
注意事项与限制
结合源码实现,使用.ksurc时有以下几点需要留意:
- 仅对 mksh 语义生效:
ENV注入是 mksh(/system/bin/sh)的 rc 加载约定。若用su -s切换到其他 shell(如 bash),是否读取ENV取决于该 shell 自身的启动行为,不能一概而论。 - 登录会话才触发 rc:rc 文件的加载与 login shell 语义相关,
su -(login)形式下 mksh 才会读取ENV指定的 rc 文件。 - 替代而非叠加:存在
.ksurc时默认/system/etc/mkshrc不再自动加载,如有依赖请自行source。 - 权限与属主:
/data/adb/ksu/目录属 ksud 工作区,创建文件后建议保持 root 属主并设置合理权限,避免被非特权应用篡改后注入恶意初始化代码。 - 路径是硬编码约定:
.ksurc路径由defs::KSURC_PATH常量固定为/data/adb/ksu/.ksurc(defs.rs),不要更改文件名或目录结构。
小结
.ksurc是 KernelSU 提供的一个轻量但实用的隐藏功能:通过在/data/adb/ksu/.ksurc放置自定义 rc 文件,用户即可统一定制su与adb root会话的 Shell 初始化环境——提示符、别名、函数与环境变量一次配置、处处生效,且无需触碰系统分区。其背后是 su.rs 中ENV环境变量的按需注入,以及 adbroot.cc 中execle钩子的环境改写,两条路径共同保证了行为的一致性。对于日常维护多台设备、或在脚本环境中频繁使用 root 会话的开发者而言,这是一个值得纳入工具箱的隐藏技巧。
【免费下载链接】KernelSUA Kernel based root solution for Android项目地址: https://gitcode.com/GitHub_Trending/ke/KernelSU
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考