Linux 内核中 SELinux 子系统的启用方式与 dummy 策略安装实战指南
本篇指南围绕 Linux 内核源码树中的 Documentation/admin-guide/LSM/SELinux.rst 展开,讲清楚 SELinux 在内核中的启用前提、策略来源选择(发行版策略 / 参考策略 / 测试用 dummy 策略),并完整还原 scripts/selinux 下 mdp 工具与 install_policy.sh 脚本生成、编译、安装 dummy 策略的全流程。读完本文,你能在不依赖发行版策略包的情况下,为任意自编译内核快速装入一个“单用户、单角色、单类型”的最小可用 SELinux 策略,完成内核安全子系统的验证与调试。
一、SELinux 在内核中的定位与文档入口
SELinux(Security-Enhanced Linux)是 Linux 内核 LSM(Linux Security Modules)框架下的强制访问控制(MAC)子系统。官方文档 SELinux.rst 首先给出了两个权威信息入口:SELinux 内核子系统的开发仓库 README,以及 SELinux 项目的用户态(userspace)资料库。这两处资料分别对应内核态实现与策略工具链,是理解该子系统的原始出处。
从源码结构看,内核侧的 SELinux 实现集中在 security/selinux 目录,核心文件包括:
- security/selinux/avc.c:AVC(Access Vector Cache),访问决策缓存,是每次访问控制决策的入口;
- security/selinux/hooks.c:将 LSM 钩子挂接到文件、网络、进程等内核对象上的实现;
- security/selinux/selinuxfs.c:
/sys/fs/selinux文件系统的实现,即策略装载与状态切换的接口; - security/selinux/ss:策略服务层,负责策略解析、SID 管理与决策执行。
该文档同时指出:如果想在实际系统中使用 SELinux,最现实的做法是直接使用发行版提供的策略包,或安装最新的参考策略(reference policy)。但如果你只是想在内核层面做功能验证或策略开发测试,官方提供了一条捷径——用 scripts/selinux 下的 mdp(make dummy policy)工具生成一个 dummy 策略。
二、dummy 策略的安装前提
按照官方文档给出的前提说明,dummy 策略方案要求目标系统已安装 SELinux 用户态工具链,具体依赖三个关键工具(这一点在 install_policy.sh 中有硬性检查):
| 工具 | 来源包(常见发行版) | 用途 |
|---|---|---|
checkpolicy |
checkpolicy | 编译内核策略,将策略源码编译为内核可装载的 blob |
setfiles / fixfiles |
policycoreutils | 按 file_contexts 为文件系统打安全标签 |
selinuxenabled |
libselinux-utils | 检测 SELinux 当前是否处于启用状态 |
脚本会在执行时依次探测这三个命令,任何一个缺失都会报错退出(参见 scripts/selinux/install_policy.sh#L9-L26)。
此外,dummy 策略本身由内核构建系统附带编译:scripts/selinux/Makefile 通过 subdir-y := mdp 将 scripts/selinux/mdp/Makefile 纳入 hostprogs 构建,mdp 二进制会在顶层 make 时自动生成。它的编译特别依赖内核头文件——HOST_EXTRACFLAGS 中注入了 -I$(srctree)/security/selinux/include 等搜索路径,因为 mdp 需要直接复用内核的 classmap.h、initial_sid_to_string.h、policycap_names.h(见 mdp.c#L32-L34),从而保证生成的策略与当前内核树所知的安全类、权限、policy capability 逐位对齐。这正是文档强调“先编译带 SELinux 的内核,再执行 make 生成 mdp”的原因。
三、官方四步安装流程详解
文档给出的操作序列共四步,下面逐步展开,并补充脚本内的实际行为。
步骤 1:编译启用 SELinux 的内核
在 make menuconfig 中打开 Security options -> SELinux Support。对应的 Kconfig 选项位于 security/selinux/Kconfig:
CONFIG_SECURITY_SELINUX:主开关,依赖SECURITY_NETWORK、AUDIT、NET、INET;CONFIG_SECURITY_SELINUX_BOOTPARAM:增加内核启动参数selinux,允许在命令行上用selinux=0禁用 SELinux——这正是 dummy 策略流程第 3 步所需的“带selinux=0重启”能力的前提;CONFIG_SECURITY_SELINUX_DEVELOP(默认 y):开发支持。开启后,内核默认以 permissive 模式启动(记录一切、不拒绝),除非在命令行指定enforcing=1;并可通过/sys/fs/selinux/enforce在 enforcing 与 permissive 之间交互切换;CONFIG_SECURITY_SELINUX_AVC_STATS(默认 y):在/sys/fs/selinux/avc/cache_stats暴露 AVC 缓存统计;CONFIG_SECURITY_SELINUX_SIDTAB_HASH_BITS(默认 9,取值 8~13)、CONFIG_SECURITY_SELINUX_AVC_HASH_BITS(默认 9,取值 9~14)、CONFIG_SECURITY_SELINUX_SID2STR_CACHE_SIZE(默认 256):分别控制 sidtab 哈希表大小、AVC 哈希表大小和 SID 到上下文字符串转换缓存。
对测试 dummy 策略而言,最小组合是 SECURITY_SELINUX=y + SECURITY_SELINUX_BOOTPARAM=y(保证 selinux=0 可用),其余保持默认即可。
步骤 2:执行 make 编译 mdp
如前所述,顶层 make 会构建 hostprog mdp,产物为 scripts/selinux/mdp/mdp.c 编译出的可执行文件,用法为:
usage: mdp [-m] policy_file context_file
-m 选项启用 MLS(多级安全)声明:额外生成 sensitivity s0/s1、category c0/c1、level s0:c0.c1 等层级定义,并为每个安全类添加 mlsconstrain 约束(要求主客体单层级且主层级支配客层级,见 mdp.c#L91-L115)。
步骤 3:确认当前未以真实策略运行 SELinux
这是官方文档特意强调的一步:如果当前系统正以“SELinux 启用 + 真实策略”状态运行,必须先带 selinux=0 重启内核再继续。原因在脚本中写得非常明确——启用状态下无法安全地对全部文件重新打标签(relabel)。install_policy.sh#L28-L33 会用 selinuxenabled 做自动检查,一旦发现 SELinux 已启用即拒绝执行。
步骤 4:运行 install_policy.sh
cd scripts/selinux
sh install_policy.sh
执行后,该脚本会为当前内核生成一份全新的 dummy 策略:只包含一个 SELinux 用户(user_u)、一个角色(base_r)和一个类型(base_t),编译策略、将 /etc/selinux/config 中的 SELINUXTYPE 设为 dummy、以 dummy 之名安装编译后的策略,并对整个文件系统重新打标签。
四、install_policy.sh 做了什么:逐段剖析
scripts/selinux/install_policy.sh 虽然只有 80 行,但完整覆盖了“生成 → 编译 → 安装 → 打标签 → 触发热切换”五个环节。
4.1 环境检查
- 必须以 root 运行(
id -u检查); - 依次探测
setfiles、checkpolicy、selinuxenabled,并用checkpolicy -V提取策略编译器版本号,用于命名编译产物(policy.$VERS); - 拒绝在 SELinux 已启用时运行(见上文)。
4.2 生成策略源文件
脚本进入 mdp/ 目录后执行:
./mdp -m policy.conf file_contexts
$CP -U allow -M -o policy.$VERS policy.conf
第一个命令用 MLS 模式生成两个文件(注意 mdp/Makefile 的 clean-files 表明这两个是本地产物):
-
policy.conf:策略源码。从 mdp.c 的源码结构看,它按如下顺序拼装:- 依据内核
secclass_map输出全部安全类(class <name>)及每个类的权限集; - 依据
initial_sid_to_string输出初始 SID; -m模式下输出 MLS 层级与mlsconstrain约束;- 打开所有 policy capability(遍历内核
selinux_policycap_names); - 定义
type base_t、role base_r,并生成allow base_t base_t:<每个安全类> *;——即该类型对自身的所有类拥有全部权限; - 定义
user user_u roles { base_r }(MLS 模式附加level s0 range s0 - s1:c0.c1); - 为每个默认 SID 指派
user_u:base_r:base_t(:s0); - 输出文件系统标注规则(详见 4.6 节)。
随后
checkpolicy以-U allow(允许allow规则)、-M(MLS 编译)选项将其编译为二进制策略policy.<版本>。 - 依据内核
-
file_contexts:文件标签规则,内容仅两行(mdp.c#L261-L262):/ user_u:object_r:base_t:s0 /.* user_u:object_r:base_t:s0即根目录与“其下一切文件”统一标注为
object_r:base_t,配合 4.1 的 root 权限检查,保证了 relabel 覆盖全盘。
4.3 铺设 /etc/selinux/dummy 策略目录
脚本在 /etc/selinux/dummy/ 下创建一套用户态工具(semanage、getenforce、init 系统等)所期望的标准布局:
/etc/selinux/dummy/
├── policy/policy.<checkpolicy版本> # 编译后的策略 blob
├── seusers # __default__:user_u:s0
└── contexts/
├── files/file_contexts # 从 mdp/ 拷入
├── failsafe_context # base_r:base_t:s0
├── default_contexts # 进程执行/转存的默认上下文
├── x_contexts # X11 窗口的 client/property 等上下文
├── dbus_contexts # 从 mdp/ 拷入
├── virtual_domain_context
└── virtual_image_context
其中 x_contexts 将 client、property、extension、selection、event 五类 X11 属性分别映射到 subject 或 object 上下文(见 install_policy.sh#L45-L51)。
4.4 改写 /etc/selinux/config
若已有 /etc/selinux/config,脚本会先将其备份为 config.bak,然后写入:
SELINUX=permissive
SELINUXTYPE=dummy
两个值得注意的点:其一,SELINUXTYPE=dummy 使用户态工具按第 4.3 节的布局寻找 dummy 策略;其二,SELINUX=permissive 表明 dummy 策略定位为测试策略——记录拒绝行为而不真正拦截,适合验证钩子与标注是否正确,而不是直接上生产(生产环境应替换为发行版或参考策略,并在确认无误后切换为 enforcing)。
4.5 全盘重新打标签
relabel 分两步:
cd /etc/selinux/dummy/contexts/files
$SF -F file_contexts /
mounts=`cat /proc/$$/mounts | \
grep -E "ext[234]|jfs|xfs|jffs2|gfs2|btrfs|f2fs|ocfs2" | \
awk '{ print $2 }'`
$SF -F file_contexts $mounts
第一步对文件系统根执行 setfiles(-F 表示忽略 file_contexts 中的不匹配项,静默处理);第二步则从 /proc/$$/mounts 中筛出支持 security.selinux xattr 的持久文件系统挂载点并逐一打标。这个文件类型清单(ext2/3/4、jfs、xfs、jffs2、gfs2、btrfs、f2fs、ocfs2)与 mdp 中生成 fs_use_xattr 规则时覆盖的文件系统类型(由 CONFIG_EXT2/EXT4/JFS/JFFS2/XFS/GFS2/BTRFS/F2FS/OCFS2_FS_SECURITY 等条件编译决定)是刻意对齐的——只有这些文件系统才能持久保存 inode 安全标签。
4.6 mdp 生成的文件系统标注规则:三种标注来源
这是 dummy 策略能“无差别覆盖”任何系统的关键。从 mdp.c#L150-L252 看,它按 inode 标签的来源分三类输出:
fs_use_xattr <fstype>:标签存于 inode 扩展属性的文件系统(ext2/3/4、jfs、jffs2、xfs、gfs2、btrfs、f2fs、ocfs2、overlay、squashfs,按内核配置条件输出);fs_use_task(pipefs、sockfs)与fs_use_trans(devpts、hugetlbfs、tmpfs、devtmpfs、mqueue):标签分别继承自分配该 inode 的任务上下文,或由任务上下文与超块标签转换得出;genfscon <fstype> /(proc、selinuxfs、sysfs、debugfs、tracefs、pstore、cgroup、cgroup2):这些虚拟文件系统不携带 xattr,其所有 inode 统一按路径前缀匹配到user_u:object_r:base_t。
三类规则共同保证了无论对象落在磁盘文件系统、tmpfs 还是 /proc 上,dummy 策略总能给出确定性的标签,不会出现未标注对象导致的强制拒绝。
4.7 触发重启后的自动 relabel
脚本最后一行:
echo "-F" > /.autorelabel
创建 /.autorelabel 标记文件,告知发行版的 init 系统在下次启动时执行带 -F 的自动重新打标流程——这确保了 permissive 模式(或重启切回 enforcing)后,标签状态与策略完全一致。
五、使用限制与后续方向
结合文档与源码,可以归纳 dummy 策略方案的适用边界:
- 能力面:单一用户/角色/类型意味着不存在真实的隔离边界——
allow base_t base_t:<所有类> *;授予自引用全权限,它验证的是“SELinux 机制是否生效”,而非“策略是否合理”; - 模式面:安装后配置为
SELINUX=permissive,日志中可见潜在拒绝但不会被实际拦截;如需 enforcing,确认标签与日志无误后修改/etc/selinux/config即可; - 回退面:原
/etc/selinux/config被备份为config.bak,配合selinux=0启动参数(前提是CONFIG_SECURITY_SELINUX_BOOTPARAM=y)可以随时回到未启用 SELinux 的状态; - 进阶方向:完成机制验证后,应按官方文档建议改用发行版策略包或参考策略,以获得真实的多类型、多角色隔离能力。策略源码的深入参考可对照 security/selinux 的实现,以及 LSM 框架下其他模块文档(如 Documentation/admin-guide/LSM/index.rst 中列出的 AppArmor、SMACK、Landlock 等)。
scripts/selinux/README 也明确指向本文所述的官方文档,作为 dummy 策略安装的唯一定义来源。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0627
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00