news 2026/9/13 23:25:20

KernelSU App Profile 完全指南:基于最小特权原则精细化管控 root 权限

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
KernelSU App Profile 完全指南:基于最小特权原则精细化管控 root 权限

KernelSU App Profile 完全指南:基于最小特权原则精细化管控 root 权限

【免费下载链接】KernelSUA Kernel based root solution for Android项目地址: https://gitcode.com/GitHub_Trending/ke/KernelSU

App Profile 是 KernelSU 提供的应用级配置机制,让 root 权限的授予不再局限于"给或不给"的二元选择。对已授权 root 的应用,它可通过 Root Profile 自定义su进程的 uid、gid、groups、capabilities 与 SELinux 域,实现防火墙只联网、冻结应用只有 shell 权限等按需授权;对普通应用,它可通过 Non-Root Profile 控制内核与模块系统对该应用的可见行为(如是否卸载 overlayfs 模块)。读完本文,你将掌握 App Profile 的数据结构、内核侧执行链路、配置语义,以及如何规避提权(escalation)风险并设计白名单/黑名单式的模块卸载策略。

一、App Profile 是什么

App Profile 是 KernelSU 提供的一种机制,用于针对不同应用定制化其配置。它分为两大类:

  • Root Profile:作用于已被授予 root 权限(即可使用su)的应用。它允许自定义su命令执行后的uidgidgroupscapabilitiesSELinux规则,从而限制 root 用户的特权。例如:只给防火墙应用授予网络权限而拒绝文件访问权限;或者只给冻结类应用授予 shell 权限而不是完整 root 权限。其核心设计理念是:让权力始终受控于最小特权原则(principle of least privilege)
  • Non-Root Profile:作用于没有 root 权限的普通应用。它可以控制内核与模块系统对这些应用的行为,例如决定由模块产生的系统修改(overlayfs 挂载)是否要对某个应用"隐藏"。

两个 Profile 的关系在 kernel/policy/allowlist.c 中有直观体现:内核缓存了default_root_profiledefault_non_root_profile两个默认配置;app_profile结构体则通过联合体(union)同时容纳 root 侧与非 root 侧的配置。

1.1 App Profile 的数据结构

KernelSU 通过 uapi/app_profile.h 定义了内核与用户态共享的 Profile 数据结构,这是整个机制的地基:

struct root_profile { __s32 uid; __s32 gid; __u32 groups_count; __s32 groups[KSU_MAX_GROUPS]; // KSU_MAX_GROUPS = 32 struct { __u64 effective; __u64 permitted; __u64 inheritable; } capabilities; char selinux_domain[KSU_SELINUX_DOMAIN]; // 64 字节 __s32 namespaces; __u64 flags; }; struct non_root_profile { bool umount_modules; }; struct app_profile { __u32 version; // 当前 KSU_APP_PROFILE_VER = 4 char key[KSU_MAX_PACKAGE_NAME]; // 通常是应用包名,特殊应用可为其他值 __s32 curr_uid; bool allow_su; union { struct { bool use_default; char template_name[KSU_MAX_PACKAGE_NAME]; struct root_profile profile; } rp_config; struct { bool use_default; struct non_root_profile profile; } nrp_config; }; };

关键约束(摘自头文件注释与 allowlist.c 的校验逻辑):

  • 包名最长 256 字节(KSU_MAX_PACKAGE_NAME),SELinux 域最长 64 字节(KSU_SELINUX_DOMAIN);
  • Linux 的NGROUPS_MAX通常是 65535,但 KernelSU 只支持32 个 supplementary groupsKSU_MAX_GROUPS);
  • capabilities采用 capabilities v3 的布局(kernel_cap_tu32[2],这里用三个__u64分别表示 effective / permitted / inheritable 三个集合);
  • rp_config.use_default/nrp_config.use_default表示该应用是否使用内核内置的默认 Profile;
  • template_name字段用于引用模板 Profile(由 ksud 保存模板数据,见下节)。

在用户态,管理器(KernelSU Manager)通过 Natives.kt 中的Profiledata class 与内核交互,字段一一对应:allowSurootUseDefaultuidgidgroupscapabilitiescontextnamespacenonRootUseDefaultumountModulesflags等。其中rules字段(SELinux 规则文本)并不下发到内核,而是保存在 ksud(用户态守护进程)中。

1.2 默认 Profile

当某个 UID 没有显式配置时,内核使用init_default_profiles()(见 allowlist.c)初始化的默认配置:

default_root_profile.uid = 0; // root default_root_profile.gid = 0; // root 组 default_root_profile.groups_count = 1; default_root_profile.groups[0] = 0; // capabilities.effective = CAP_FULL_SET,即完整能力集 default_root_profile.namespaces = KSU_NS_INHERITED; // selinux_domain = "u:r:ksu:s0"(KSU_DEFAULT_SELINUX_DOMAIN) default_non_root_profile.umount_modules = true; // 默认卸载模块!

也就是说:默认 Root Profile 是完整权限的 root(uid/gid=0、完整 capabilities、u:r:ksu:s0域、继承挂载命名空间),默认 Non-Root Profile 会卸载模块(umount modules 默认开启)。这正对应文档中"管理器设置界面的 'Umount modules by default' 开关默认开启"的行为——从源码看,该开关直接写入default_non_root_profile.umount_modules(allowlist.c,由特殊保留 UID9999与 key"$"标识)。

二、Root Profile:按需裁剪 root 的"能力集"

Root Profile 允许自定义su后 root 进程的五个维度:UID/GID/Groups、Capabilities、SELinux 域、命名空间与标志位。内核在su提权时通过 escape_with_root_profile() 统一落地。

2.1 UID、GID 与 Groups:身份即权限

Linux 系统有两个核心概念:用户(user)与组(group)。每个用户有唯一的用户 ID(UID),一个用户可属于多个组,每个组有组 ID(GID)。UID/GID 用于标识系统用户并决定其可访问的系统资源。

  • UID 为0的用户称为 root 用户,GID 为0的组称为 root 组,root 用户组通常拥有最高系统特权。
  • 在 Android 中,每个应用(共享 UID 除外)都是一个独立用户,拥有唯一 UID。例如:0表示 root,1000表示system2000表示 ADB shell,1000019999表示普通应用。
  • 需要注意:这里说的 UID 与 Android 的多用户(multiple users)或工作资料(Work profile)不是一回事。工作资料是通过划分 UID 区间实现的,例如10000-19999代表主用户,而110000-119999代表工作资料,其中的每个普通应用仍然有自己独立的 UID。这一约定在内核侧由PER_USER_RANGE(100000)等宏体现,见 allowlist.h。

每个应用可有多个组,GID 表示主组(primary group,通常与 UID 一致),其余为附加组(supplementary groups)。部分权限通过组来控制,例如网络访问或蓝牙访问。在 ADB shell 中执行id命令可直观看到这些信息:

oriole:/ $ id uid=2000(shell) gid=2000(shell) groups=2000(shell),1004(input),1007(log),1011(adb),1015(sdcard_rw),1028(sdcard_r),1078(ext_data_rw),1079(ext_obb_rw),3001(net_bt_admin),3002(net_bt),3003(inet),3006(net_bw_stats),3009(readproc),3011(uhid),3012(readtracefs) context=u:r:shell:s0

这里 UID 是2000,GID(主组)也是2000,同时还属于若干附加组,例如inet(表示可创建AF_INETAF_INET6套接字)和sdcard_rw(表示对 SD 卡的读写权限)。

Root Profile 的用法:例如将某 root 应用的 UID 设为2000,则它使用su时实际权限只有 ADB shell 级别;再移除inet组,即可阻止su访问网络。内核侧的组设置逻辑在 setup_groups():当groups_count == 1 && groups[0] == 0时直接切换到 root 组并提前返回;否则分配group_info、逐项校验 GID 有效性(gid_valid)、排序并set_groups()到新的 cred 上。

重要边界(文档明确强调):App Profile 只控制su之后 root 进程的权限,不控制应用自身的权限。如果应用已在系统层面申请了网络权限,那么它不使用su也能访问网络;从su移除inet组只阻止su访问网络。

内核强制执行:Root Profile 在内核中强制实施,不依赖 root 应用的自愿配合。与通过su切换用户/组不同,su权限的授予完全由用户(而非开发者)控制。提权入口escape_with_root_profile()会重新分配凭据(prepare_creds/commit_creds)、按 Profile 设置四组 UID/GID(uid/suid/euid/fsuidgid/sgid/egid/fsgid)、刷新cred->userucounts的进程计数归属,并同步更新线程组的 tracepoint 标记。

2.2 Capabilities:把"全知全能"拆成可独立开关的单元

Capabilities 是 Linux 的权限分离(privilege separation)机制。在做权限检查时,传统 UNIX 将进程分为两类:

  • 特权进程:有效用户 ID(effective UID)为 0(超级用户/root),绕过内核所有权限检查;
  • 非特权进程:有效 UID 非 0,需基于进程凭证(通常为:有效 UID、有效 GID 与附加组列表)接受完整权限检查。

从 Linux 2.2 起,Linux 把传统上与超级用户绑定的特权拆分为独立的单元——capabilities,每个 capability 可被独立启用或禁用,每个 capability 代表一个或多个特权。例如CAP_DAC_READ_SEARCH表示绕过文件读取权限检查以及目录读/执行权限检查的能力;如果一个有效 UID 为0(root)的用户缺少CAP_DAC_READ_SEARCH(或更高)capability,那么即使他是 root,也不能随意读取文件。

Root Profile 允许自定义su之后 root 进程的 capabilities,从而实现"部分 root 权限"的授予。与 UID/GID 不同,某些 root 应用必须使用 UID0;此时为这个 UID 为0的 root 用户限制 capabilities,就可以限制其被允许执行的操作。

强烈建议:Linux 的 capabilities(7) 官方手册 详细解释了每个 capability 代表的能力;若要自定义 capabilities,务必先阅读该文档。(此处链接为文档内原始外部引用,仅供理解,不构成对仓库内容的引用。)

内核侧落地方式(app_profile.c):Profile 中的effective能力集被同时写入新 cred 的cap_effectivecap_permittedcap_bset(bounding set)。也就是说,su进程的能力上限完全由 Profile 决定——被裁剪掉的能力在任何情况下都无法再获得。

2.3 SELinux:默认拒绝的细粒度访问控制

SELinux 是一种强大的强制访问控制(Mandatory Access Control, MAC)机制,遵循默认拒绝原则:任何未被显式允许的动作都会被拒绝。SELinux 有两种全局模式:

  1. 宽容模式(Permissive mode):拒绝事件被记录但执行;
  2. 强制模式(Enforcing mode):拒绝事件被记录执行。

警告(文档原文):现代 Android 系统高度依赖 SELinux 来保证整体系统安全。强烈建议不要使用任何运行在"宽容模式"下的自定义系统,因为与完全开放的系统相比它没有任何显著优势。

SELinux 的完整概念非常复杂,超出了本文档的讨论范围,建议先通过以下资源理解其工作机制(文档内提供的参考资料):Wikipedia: Security-Enhanced Linux、Red Hat: What Is SELinux?、ArchLinux Wiki: SELinux。

Root Profile 允许自定义su后 root 进程的 SELinux 上下文。典型场景下,应用执行su后进程会切换到无限制访问的 SELinux 域,如u:r:ksu:s0(对应源码中KERNEL_SU_CONTEXT,见 selinux.h);通过 Root Profile 可将该域切换到自定义域,例如u:r:app1:s0,并为该域定义一系列规则:

type app1 enforce app1 typeattribute app1 mlstrustedsubject allow app1 * * *

注意:allow app1 * * *仅为演示用途。实际使用中不应广泛采用这条规则,因为它与宽容模式几乎没有区别。内核通过 setup_selinux()(声明见 selinux.h)在提权时写入selinux_domain,且校验逻辑要求该域非空、长度小于 64 字节(allowlist.c)。

2.4 命名空间与其他字段

除了文档重点讲解的 UID/GID/Groups、Capabilities、SELinux 之外,root_profile还包含两个字段,可结合源码一并理解:

  • namespaces:挂载命名空间模式,取值定义在 su_mount_ns.h:KSU_NS_INHERITED(0) 继承、KSU_NS_GLOBAL(1) 全局、KSU_NS_INDIVIDUAL(2) 独立。提权末尾会调用setup_mount_ns(profile->namespaces)(app_profile.c)。
  • flags:目前仅定义FLAG_KSU_NO_NEW_PRIVS1ULL << 0,app_profile.h),对应下方"提权防护"一节。

2.5 提权风险(Escalation)与 NO_NEW_PRIVS 防护

如果 Root Profile 配置不当,可能发生提权(escalation)场景:Root Profile 施加的限制意外失效。

举例说明(文档给出的典型场景):假如你把 root 权限授予了 ADB shell 用户(这很常见),然后又给某个普通应用授予 root 权限,但将其 Root Profile 的 UID 配置为2000(即 ADB shell 用户的 UID),那么该应用可以通过执行两次su获得完整 root 权限:

  1. 第一次执行su:受 App Profile 约束,切换到 UID2000(ADB shell)而非0(root);
  2. 第二次执行su:由于当前 UID 是2000,而配置中已经给 UID2000(ADB shell)授予了 root 权限,应用将获得完整 root 权限。

防护手段:可以在自定义 App Profile 中启用NO_NEW_PRIVS标志(即FLAG_KSU_NO_NEW_PRIVS)。启用后,内核在提权完成时通过set_thread_flag(TIF_KSU_DISABLE_ESCAPE_WITH_ROOT)设置线程标志(见 app_profile.c 与 app_profile.h);当该标志存在时,后续的escape_with_root_profile()会直接拒绝再次提权(app_profile.c)。

务必注意(文档强调):该标志阻止 KernelSU 为进程再次提升权限;进程仍可通过其他 Linux 机制逃逸。因此请对你的权限设置保持极度谨慎。

在内核 supercall 层,还提供了KSU_IOCTL_DISABLE_ESCAPE_TO_ROOT命令(dispatch.c),root 会话可直接调用以禁止后续通过su再次提权,作为对 Profile 标志的补充手段。

三、Non-Root Profile:对普通应用"隐藏"系统修改

3.1 Umount Modules:两种工作模式

KernelSU 提供 systemless(无系统修改)机制来修改系统分区,其实现依赖 overlayfs 挂载。然而某些应用对这种行为很敏感(例如会检测 root 的金融/银行类应用)。为此,可以通过设置"Umount modules"选项,为这些应用卸载已挂载的模块。

管理器设置界面还提供了"Umount modules by default"开关,默认开启——这意味着默认情况下 KernelSU(或某些模块)会为应用卸载模块,除非额外设置。如果你不喜欢该默认设置,或它影响了某些应用,你有两种选择:

  1. 白名单模式:保持"Umount modules by default"开启,并在 App Profile 中针对需要加载模块的应用单独关闭"Umount modules"选项;
  2. 黑名单模式:关闭"Umount modules by default",并在 App Profile 中针对需要卸载模块的应用单独开启"Umount modules"选项。

从源码看,ksu_uid_should_umount(uid)(allowlist.c)完整实现了这一决策树:

  • 管理器自身(ksu_get_manager_appid()匹配的 UID)永不卸载模块;
  • 没有 App Profile 的应用 → 使用default_non_root_profile.umount_modules
  • 已授予su的应用 → 不卸载(res = false);
  • 有 Non-Root Profile 的应用 →use_default时跟随默认值,否则使用 Profile 中显式配置的umount_modules

该决策通过KSU_IOCTL_UID_SHOULD_UMOUNTioctl 暴露给用户态查询(dispatch.c)。

内核版本差异(文档重要提示)

  • 内核版本 5.10 及以上的设备上,内核本身会执行模块的卸载,无需额外动作;
  • 内核版本低于 5.10的设备上,这个开关只是纯粹的配置项,KernelSU 本身不采取任何行动;若要在 5.10 之前的内核上使用该选项,需要将fs/namespace.c中的path_umount函数反向移植(backport)。某些模块(如 Zygisksu)也会读取该开关来判断是否需要卸载模块。

3.2 Profile 的存储与加载

App Profile 在内核中通过哈希表(allow_list,见 allowlist.c)以 UID 为键维护,并通过/data/adb/ksu/.allowlist文件持久化:

  • 写入:ksu_persistent_allow_list()以"魔数0x7f4b5355+ 版本号 + 逐个app_profile结构体"的二进制格式落盘(allowlist.c);
  • 读取:ksu_load_allow_list()校验魔数与版本(当前FILE_FORMAT_VERSION = 4),并支持从旧版本(2/3)迁移,例如把u:r:su:s0域迁移为u:r:ksu:s0、为 v3 自动补上FLAG_KSU_NO_NEW_PRIVS(allowlist.c);
  • 清理:ksu_prune_allowlist()在开机完成后删除已卸载应用的记录(保留 UID99991053(WebView zygote)等特殊条目,allowlist.c)。

用户态管理器通过KSU_IOCTL_GET_APP_PROFILE/KSU_IOCTL_SET_APP_PROFILE两个 ioctl 读写 Profile(dispatch.c),且这两个命令只允许管理器(manager)调用(映射表中perm_check = only_manager)。设置成功后内核会立即持久化并刷新运行中进程的标记。

四、与模块系统的协作:模板 Profile 与规则下发

App Profile 还支持**模板(Template)**复用:rp_config.template_name指向一个具名模板,模板的实际内容由 ksud 保存(管理器 UI 中的TemplateConfig组件,见 ProfileConfig.kt)。Profile 中的rules字段(SELinux 规则文本)也不会下发给内核,而是由 ksud 负责解析并注入内核的 sepolicy,经由KSU_IOCTL_SET_SEPOLICYhandle_sepolicy()处理(dispatch.c)。这意味着"自定义 SELinux 域 + 配套规则"的整体方案是:管理器把规则交给 ksud,ksud 编译/注入规则,内核在执行su时按 Profile 切换到对应域

同时,KernelSU 的 feature 机制(feature.c)允许内核与模块注册/查询/设置能力开关(KSU_IOCTL_GET_FEATURE/KSU_IOCTL_SET_FEATURE),模块可以据此感知"Umount modules by default"等全局配置并调整自身行为——这正是文档所述"某些模块会使用该开关判断是否需要卸载模块"的底层通道。

五、实践建议与配置清单

基于文档与源码,整理一份安全配置清单:

配置项位置建议
uid / gid / groupsRoot Profile按最小特权原则设置;不要轻易把普通应用配成其他已授权 UID(防提权)
capabilitiesRoot Profile仅保留应用必需能力;修改前阅读 capabilities(7) 手册
selinux_domainRoot Profile定义独立域并配套最小化 allow 规则;避免allow app1 * * *
NO_NEW_PRIVS 标志Root Profile flags强烈建议开启,阻断经su的二次提权
umount_modulesNon-Root Profile配合全局默认开关,选择白名单或黑名单策略
template_nameRoot Profile复用模板,保持配置一致性

核心要点回顾:

  1. App Profile 的默认 Root Profile 是完整 root,默认 Non-Root Profile 卸载模块(umount_modules = true),一切定制都从这两份默认配置出发;
  2. Root Profile 在内核escape_with_root_profile()中强制执行,覆盖 UID/GID/Groups、capabilities(effective/permitted/bounding set)、SELinux 域、命名空间与 flags,不依赖应用的自觉性;
  3. 配置不当存在二次su提权风险,NO_NEW_PRIVS只能阻断 KernelSU 通道的提权,权限设计仍需谨慎;
  4. "Umount modules"在 5.10 以下内核仅是配置项(需自行 backportpath_umount),在 5.10 及以上内核由内核实际执行,模块可通过 feature 机制读取该配置调整行为。

如需进一步深入,可继续阅读仓库中的 uapi/app_profile.h(数据结构)、kernel/policy/app_profile.c(提权实现)、kernel/policy/allowlist.c(默认配置/持久化/卸载决策)以及管理器侧的 Natives.kt(用户态 Profile 模型)与 AppProfileConfig(配置界面入口)。

【免费下载链接】KernelSUA Kernel based root solution for Android项目地址: https://gitcode.com/GitHub_Trending/ke/KernelSU

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/13 23:25:07

ICA盲源分离实战:从FastICA到双麦克风语音分离

简介&#xff1a;面向信号处理与机器学习初学者的 ICA 盲源分离 MATLAB 实现包&#xff0c;以 5 个 .m 源文件&#xff08;约 5KB&#xff09;浓缩了经典 Bell-Sejnowski 独立成分分析算法核心流程&#xff0c;适合用来理解盲分离从混合信号中恢复独立源的基本原理。包内代码覆…

作者头像 李华
网站建设 2026/9/13 23:24:29

小米 Home Assistant 集成浴霸模式控制丢失完整修复指南

小米 Home Assistant 集成浴霸模式控制丢失完整修复指南 【免费下载链接】ha_xiaomi_home Xiaomi Home Integration for Home Assistant 项目地址: https://gitcode.com/GitHub_Trending/ha/ha_xiaomi_home 小米 Home Assistant 集成 ha_xiaomi_home 让你在 Home Assist…

作者头像 李华
网站建设 2026/9/13 23:24:14

PDF补丁丁:一个便携程序搞定PDF去限制、合并、生成书签的8类杂活

PDF补丁丁&#xff1a;一个便携程序搞定PDF去限制、合并、生成书签的8类杂活 【免费下载链接】PDFPatcher PDF补丁丁——PDF工具箱&#xff0c;可以编辑书签、剪裁旋转页面、解除限制、提取或合并文档&#xff0c;探查文档结构&#xff0c;提取图片、转成图片等等 项目地址: …

作者头像 李华
网站建设 2026/9/13 23:22:28

油包水液滴生成COMSOL仿真:从建模到避坑全流程解析

做微流控仿真这些年&#xff0c;油包水液滴生成一直是个绕不开的话题。我第一次用COMSOL跑通液滴脱落的瞬间&#xff0c;看着界面从一根细长的颈慢慢被剪切力扯断&#xff0c;变成一个完整的液滴被油相带走&#xff0c;确实有种“看见了微观世界”的奇妙感。但说实话&#xff0…

作者头像 李华
网站建设 2026/9/13 23:22:20

记忆管理工具memU的核心机制与实战技巧

1. 记忆管理工具的核心逻辑解析当第一次听说memU这个工具时&#xff0c;我下意识以为又是某个花哨的记忆软件。但实际使用三个月后&#xff0c;发现它在记忆处理机制上确实有些独到之处。这类工具本质上都在解决同一个问题&#xff1a;如何帮助用户更高效地获取、存储和提取记忆…

作者头像 李华