首页
/ Linux 内核中 SELinux 子系统的启用方式与 dummy 策略安装实战指南

Linux 内核中 SELinux 子系统的启用方式与 dummy 策略安装实战指南

2026-09-06 13:46:14作者:曹令琨Iris

本篇指南围绕 Linux 内核源码树中的 Documentation/admin-guide/LSM/SELinux.rst 展开,讲清楚 SELinux 在内核中的启用前提、策略来源选择(发行版策略 / 参考策略 / 测试用 dummy 策略),并完整还原 scripts/selinuxmdp 工具与 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 目录,核心文件包括:

该文档同时指出:如果想在实际系统中使用 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 := mdpscripts/selinux/mdp/Makefile 纳入 hostprogs 构建,mdp 二进制会在顶层 make 时自动生成。它的编译特别依赖内核头文件——HOST_EXTRACFLAGS 中注入了 -I$(srctree)/security/selinux/include 等搜索路径,因为 mdp 需要直接复用内核的 classmap.hinitial_sid_to_string.hpolicycap_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_NETWORKAUDITNETINET
  • 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/s1category c0/c1level 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 检查);
  • 依次探测 setfilescheckpolicyselinuxenabled,并用 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/Makefileclean-files 表明这两个是本地产物):

  • policy.conf:策略源码。从 mdp.c 的源码结构看,它按如下顺序拼装:

    1. 依据内核 secclass_map 输出全部安全类(class <name>)及每个类的权限集;
    2. 依据 initial_sid_to_string 输出初始 SID;
    3. -m 模式下输出 MLS 层级与 mlsconstrain 约束;
    4. 打开所有 policy capability(遍历内核 selinux_policycap_names);
    5. 定义 type base_trole base_r,并生成 allow base_t base_t:<每个安全类> *;——即该类型对自身的所有类拥有全部权限
    6. 定义 user user_u roles { base_r }(MLS 模式附加 level s0 range s0 - s1:c0.c1);
    7. 为每个默认 SID 指派 user_u:base_r:base_t(:s0)
    8. 输出文件系统标注规则(详见 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/ 下创建一套用户态工具(semanagegetenforce、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_contextsclientpropertyextensionselectionevent 五类 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 标签的来源分三类输出:

  1. fs_use_xattr <fstype>:标签存于 inode 扩展属性的文件系统(ext2/3/4、jfs、jffs2、xfs、gfs2、btrfs、f2fs、ocfs2、overlay、squashfs,按内核配置条件输出);
  2. fs_use_task(pipefs、sockfs)与 fs_use_trans(devpts、hugetlbfs、tmpfs、devtmpfs、mqueue):标签分别继承自分配该 inode 的任务上下文,或由任务上下文与超块标签转换得出;
  3. 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 策略方案的适用边界:

  1. 能力面:单一用户/角色/类型意味着不存在真实的隔离边界——allow base_t base_t:<所有类> *; 授予自引用全权限,它验证的是“SELinux 机制是否生效”,而非“策略是否合理”;
  2. 模式面:安装后配置为 SELINUX=permissive,日志中可见潜在拒绝但不会被实际拦截;如需 enforcing,确认标签与日志无误后修改 /etc/selinux/config 即可;
  3. 回退面:原 /etc/selinux/config 被备份为 config.bak,配合 selinux=0 启动参数(前提是 CONFIG_SECURITY_SELINUX_BOOTPARAM=y)可以随时回到未启用 SELinux 的状态;
  4. 进阶方向:完成机制验证后,应按官方文档建议改用发行版策略包或参考策略,以获得真实的多类型、多角色隔离能力。策略源码的深入参考可对照 security/selinux 的实现,以及 LSM 框架下其他模块文档(如 Documentation/admin-guide/LSM/index.rst 中列出的 AppArmor、SMACK、Landlock 等)。

scripts/selinux/README 也明确指向本文所述的官方文档,作为 dummy 策略安装的唯一定义来源。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.13 K
2.75 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
857
1.35 K
docsdocs
暂无描述
Markdown
897
5.8 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
529
593
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
915
1.83 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.58 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.35 K
1.46 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
1.01 K
515
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
547
388