ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

KernelSU App Profile 完整指南:用 Root Profile 与模块卸载策略精细管控应用权限

KernelSU App Profile 完整指南:用 Root Profile 与模块卸载策略精细管控应用权限 KernelSU App Profile 完整指南用 Root Profile 与模块卸载策略精细管控应用权限【免费下载链接】KernelSUA Kernel based root solution for Android项目地址: https://gitcode.com/GitHub_Trending/ke/KernelSUApp Profile应用配置是 KernelSU 提供的一种针对每一个应用自定义其使用配置的机制对于已授予 root 权限的应用它可以定制su进程的uid、gid、groups、capabilities与SELinux context把 root 权限关进笼子里对于普通应用它可以控制内核与模块系统是否对应用执行卸载模块等隐藏性操作。读完本文你将掌握 Root Profile 与 Non Root Profile 的完整概念、配置思路、逃逸风险与规避方法以及这些配置在内核中是如何被强制执行的。什么是 App ProfileKernelSU 的内核实现中App Profile 对应一份以应用包名为key、以应用 UID 为检索依据的配置记录。从内核 UAPI 头文件 uapi/app_profile.h 可以看到每个配置项包含version当前为KSU_APP_PROFILE_VER 4、key通常是应用包名最长KSU_MAX_PACKAGE_NAME256 字节、curr_uid当前 UID与allow_su是否允许使用 su四个基础字段并在此之上按应用是否拥有 root 权限拆分为两类配置Root Profile针对可以使用su的应用定制su执行后的进程身份与权限边界Non Root Profile针对未授予 root 权限的普通应用控制内核与模块系统对该应用的行为目前核心字段是umount_modules。两类配置通过app_profile结构体中的联合体union区分由 kernel/policy/allowlist.c 中的ksu_set_app_profile/ksu_get_app_profile管理并持久化到/data/adb/ksu/.allowlist文件带 magic 与版本号的二进制格式。Root Profile限制 su 的权限边界对于被授予 root 权限的应用Root Profile 可以自定义执行su后 root 程序的uid、gid、groups、capabilities与SELinux context规则。典型场景包括给防火墙应用仅授予网络权限而不授予文件访问权限给冻结类应用仅授予 shell 权限而不是直接给 root——通过最小化权限原则把权力关进笼子里。UID、GID 与 groupsLinux 系统中有用户与群组两个概念。每个用户有一个用户 IDUID一个用户可以属于多个群组每个群组也有群组 IDGID这些 ID 用于识别用户并决定其可访问的系统资源。UID 为 0 的用户称为 root 用户GID 为 0 的群组称为 root 群组通常拥有系统最高权限。在 Android 上每个应用都是一个独立用户不考虑 share uid 的情况拥有唯一 UID。典型映射如下UID身份0root1000system2000ADB shell10000–19999普通应用补充这里的 UID 与 Android 多用户/工作资料Work Profile是不同概念。工作资料本质是对 UID 范围分片实现的例如10000-19999是主用户110000-119999是工作资料其中每一个普通应用都拥有自己独有的 UID。内核侧 kernel/policy/allowlist.h 用PER_USER_RANGE 100000、FIRST_APPLICATION_UID 10000、LAST_APPLICATION_UID 19999等宏体现这一分片模型。每个应用可属于多个群组GID 是主群组通常与 UID 一致其余为补充群组groups。部分权限通过群组控制例如网络访问、蓝牙等。在 ADB shell 中执行id命令的典型输出oriole:/ $ id uid2000(shell) gid2000(shell) groups2000(shell),1004(input),1007(log),1011(adb),1015(sdcard_rw),1028(sdcard_r),1078(ext_data_ww) (ext_obb_rw),3001(net_bt_admin),3002(net_bt),3003(inet),3006(net_bw_stats),3009(readproc),3011(uhid),3012(readreadtracefs:s05:其中 UID 为2000GID 也为2000此外还属于多个补充组例如inet组代表可以创建AF_INET/AF_INET6socket访问网络sdcard_rw代表可读写 sdcard 等。KernelSU 的 Root Profile 可以自定义执行su后 root 程序的 UID、GID 和 groups。例如将某 root 应用的 Root Profile UID 设为2000则该应用使用su时实际权限等级为 ADB shell若再移除 groups 中的inet则该su无法访问网络。注意App Profile 只控制 root 应用使用su之后的权限并不控制应用本身的权限。如果应用本身申请了网络访问权限即使不使用su也能访问网络为su移除inet群组只是让su无法访问网络。与应用通过su主动切换用户/群组不同Root Profile 是在内核中强制实施的不依赖 root 应用的自觉行为su权限的授予完全取决于用户而非开发者。从源码看这一强制的核心实现在 kernel/policy/app_profile.c 的escape_with_root_profile()它会用 profile 中的值覆盖新凭据的uid/suid/euid/fsuid与gid/sgid/egid/fsgid再调用setup_groups()写入主/补充群组KSU_MAX_GROUPS上限为 32随后setup_selinux()切换 SELinux 域、commit_creds()提交凭据最后disable_seccomp()关闭 seccomp 过滤完成一次不可绕过的提权。CapabilitiesCapabilities 是 Linux 的分权机制。传统 UNIX 将进程分为特权进程有效 UID 为 0即超级用户/root与非特权进程有效 UID 非零特权进程绕过所有内核权限检查非特权进程则基于凭据有效 UID、有效 GID 与补充群组列表做完整权限检查。从 Linux 2.2 起Linux 将传统上与超级用户关联的特权拆分为可独立启用/停用的单元即 Capabilities也译作权能。每个 Capability 代表一项或一类权限。例如CAP_DAC_READ_SEARCH代表绕过文件读取权限检查、目录读取与执行权限检查的能力——如果一个有效 UID 为 0 的用户没有CAP_DAC_READ_SEARCH或更高权限即使它是 root 也无法随意读取文件。KernelSU 的 Root Profile 可自定义su后 root 程序的 Capabilities从而实现部分 root 权限。与 UID/GID 不同有些 root 应用确实需要su后 UID 为0此时可通过限制这个 UID 为 0 的 root 用户的 Capabilities 来约束其可执行的操作。强烈建议Linux 内核的 capabilities 手册页详细解释了每一项 Capability 所代表的能力自定义 Capabilities 前务必先通读该手册。内核 UAPI 将 Capabilities 建模为effective、permitted、inheritable三组 64 位集合见 uapi/app_profile.h 中struct root_profile。实现上kernel/policy/app_profile.c 将 profile 的capabilities.effective同时复制到内核凭据的cap_effective、cap_permitted与cap_bset——也就是说被授予的能力集合会贯穿有效集、许可集、边界集确保su子进程无法重新获得未授予的能力。默认的 root profilekernel/policy/allowlist.c 的init_default_profiles则使用CAP_FULL_SET即完整能力集。SELinuxSELinux 是一种强大的强制访问控制MAC机制按默认拒绝原则运作任何未经明确允许的行为都会被拒绝。SELinux 有两种全局模式宽容模式Permissive权限拒绝事件被记录但不强制执行强制模式Enforcing权限拒绝事件被记录并且强制执行。警告现代 Android 系统极度依赖 SELinux 保障整体安全强烈建议不要使用任何以宽容模式运行的自定义系统那与裸奔几乎没有区别。SELinux 完整概念较复杂建议先通过 Wikipedia、Red Hat 的 What Is SELinux、Arch Linux Wiki 的 SELinux 条目了解其运作原理。KernelSU 的 Root Profile 可以自定义执行su后 root 程序的 SELinux context并可针对该 context 设定特定访问控制规则从而更精细地控制 root 权限。通常应用执行su后进程会被切换到不受任何限制的 SELinux 域例如u:r:ksu:s0通过 Root Profile 可将其切换到自定义域例如u:r:app1:s0然后为该域制定规则type app1 enforce app1 typeattribute app1 mlstrustedsubject allow app1 * * *注意这里的allow app1 * * *仅为演示方便而使用实际配置中不应使用因为它与宽容模式区别不大。从内核实现看切换域的动作由 kernel/selinux/selinux.c 的setup_selinux()完成通过security_secctx_to_secid将域字符串解析为 SID写入 task 的 security 结构并清空create_sid、keycreate_sid、sockcreate_sid等派生 SID。而为自定义域注入规则的能力则体现在 kernel/selinux/rules.c它复制当前 sepolicy执行ksu_type、ksu_permissive、ksu_typeattribute、ksu_allow、ksu_allowxperm等操作后原子切换策略并reset_avc_cache()重置 AVC 缓存使新规则立即生效。KernelSU 自身的ksu域默认被声明为 permissive 并加入mlstrustedsubject、netdomain、bluetoothdomain等属性。逃逸配置不当的后果如果 Root Profile 配置不合理可能发生逃逸Root Profile 的限制意外失效。例如你为 ADB shell 用户UID2000配置了允许 root 权限这是相当常见的情况又给某个普通应用允许 root但将其 Root Profile 的 UID 配成了2000此时该应用可以执行两次su获得完整 root 权限第一次suApp Profile 强制生效正常切换到 UID2000adb shell而非0root第二次su此时它 UID 已是2000而你对2000配置了允许 root它将获得完整的 root 权限提示你可以在自定义 App Profile 中启用NO_NEW_PRIVS标志阻止该进程再次通过su逃逸提权。内核侧对应FLAG_KSU_NO_NEW_PRIVS定义于 uapi/app_profile.hkernel/policy/app_profile.c 的escape_with_root_profile()在检测到该标志后会设置线程标志位TIF_KSU_DISABLE_ESCAPE_WITH_ROOT后续再次提权时会在入口处直接拒绝打印 Already root / disable escape 并中止。但该标志仅阻止 KernelSU 为该进程提权进程仍可利用其他 Linux 机制逃逸因此请务必审慎设置权限。Non Root Profile控制模块系统行为对于未被授予 root 权限的普通应用App Profile 可以控制内核以及模块系统对该应用的行为例如是否需要对该应用卸载模块造成的修改隐藏痕迹类操作。内核与模块系统会依据此配置决定是否执行卸载。卸载模块Umount ModulesKernelSU 提供了一种无须直接修改系统分区systemless的机制来修改系统分区这是通过挂载 OverlayFS 实现的。但部分应用对这类挂载比较敏感例如银行、支付类应用会检测挂载痕迹因此可针对这些应用开启卸载模块把挂载在它们身上的模块卸掉。KernelSU 管理器的设置界面还提供一个**预设卸载模块开关默认开启**即如果不针对应用做额外设置默认情况下 KernelSU 或某些模块会对此应用执行卸载。如果不喜欢此默认行为你有两种策略白名单模式保持预设卸载模块开启然后针对不需要卸载模块的应用在其 App Profile 中单独关闭卸载模块黑名单模式关闭预设卸载模块然后针对需要卸载模块的应用在其 App Profile 中单独开启卸载模块。提示在 5.10 及以上内核上KernelSU 内核无需任何修改即可卸载模块但在 5.10 以下的设备上这个开关仅仅是设置KernelSU 本身不会做任何动作。若希望在 5.10 之前的内核上支持卸载模块需要将path_umount函数向后移植到fs/namespace.c具体参见如何为非 GKI 内核整合 KernelSU。一些模块如 ZygiskNext也会通过这个设置决定是否需要卸载。从源码看卸载决策链完整贯穿内核kernel/policy/allowlist.c 的ksu_uid_should_umount(uid)是决策核心管理器自身 UID 永不卸载若应用没有任何 profile 记录则返回全局默认值default_non_root_profile.umount_modules初始化时为true即默认卸载若该应用已被授予su则不卸载否则取 profile 中nrp_config的配置未单独设置时同样回落到默认值应用 fork 时kernel/feature/kernel_umount.c 的ksu_handle_umount()会先判断新 UID 是否为普通应用 / WebView zygote / isolated 进程再调用ksu_uid_should_umount()并校验父进程确实来自 zygote 后遍历模块挂载列表逐个path_umount卸载ksud 用户态也可通过KSU_UID_SHOULD_UMOUNT超调用见 kernel/supercall/dispatch.c查询某 UID 是否应卸载模块系统据此决定自己的行为内核支持通过KSU_FEATURE_KERNEL_UMOUNT特性开关kernel_umount整体启用/停用内核卸载能力。另外非 root profile 的默认值default_non_root_profile是可配置的当某个curr_uid为保留值 9999KSU_APP_PROFILE_PRESERVE_UID、key为$的特殊 profile 被写入时kernel/policy/allowlist.c 的ksu_set_app_profile()会同步更新全局默认非 root profile——这正是管理器预设卸载模块开关在内核中的落点。配置的持久化与版本迁移App Profile 记录由内核统一持久化ksu_persistent_allow_list()会把哈希表中的全部 profile 以二进制格式写入/data/adb/ksu/.allowlist文件头含 magic0x7f4b5355 KSU与格式版本号开机时ksu_load_allow_list()读取并校验该文件逐条恢复。当前格式版本为 4加载器对旧版本v2/v3会自动迁移例如 v2 中u:r:su:s0域会被迁移为默认的u:r:ksu:s0v3 会自动为 root profile 补上FLAG_KSU_NO_NEW_PRIVS标志见 kernel/policy/allowlist.c 的migrate_profile()。此外ksu_prune_allowlist()会在应用卸载后清理失效条目保留 UID 9999 与 WebView zygote 1053 两个特殊项。总结App Profile 是 KernelSU 在能否 root之外提供的第二层精细治理维度Root Profile从 UID/GID/groups、Capabilities、SELinux context 三个层面约束su之后的进程且由内核强制实施配置时需警惕二次su逃逸必要时启用NO_NEW_PRIVS标志Non Root Profile通过卸载模块配置决定内核与模块系统是否对应用隐藏 OverlayFS 挂载并可与管理器的预设卸载模块开关组合出白名单/黑名单两种运维模式所有配置以二进制形式持久化于/data/adb/ksu/.allowlist支持版本迁移与卸载清理可在重启后自动恢复。结合 uapi/app_profile.h、kernel/policy/app_profile.c、kernel/policy/allowlist.c、kernel/feature/kernel_umount.c 与 kernel/selinux/rules.c 等源码你可以精确理解每一项配置在内核中的落点与生效路径从而为每个应用设计出既满足功能需求又符合最小权限原则的 profile。【免费下载链接】KernelSUA Kernel based root solution for Android项目地址: https://gitcode.com/GitHub_Trending/ke/KernelSU创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表