1. SELinux 基础架构与安全上下文

SELinux(Security-Enhanced Linux)是 Linux 内核的强制访问控制(MAC)子系统。与传统的自主访问控制(DAC)不同,SELinux 对每个主体(进程)和客体(文件、端口、设备)都赋予一个安全上下文,并由内核中的策略引擎根据预定义规则决定是否允许访问。理解这三种模式、安全上下文格式以及进程/文件的上下文关系,是编写策略和构建沙箱的第一步。

1.1 三种运行模式

模式说明典型场景
Enforcing强制执行策略,拒绝的访问会被阻止并记录 AVC 审计日志生产服务器、沙箱隔离环境
Permissive允许所有访问,但拒绝行为仍会记录到审计日志调试策略、规则验证、迁移过渡
Disabled完全关闭 SELinux,不加载策略、不检查上下文临时绕过、不支持 SELinux 的旧应用
实践经验:在编写新策略或调试沙箱隔离时,先将系统切换为 Permissive 模式,收集所有拒绝日志,再批量编写 allow 规则,最后切回 Enforcing 验证。禁用模式应仅用于故障排除,禁止长期使用。

1.2 安全上下文格式

安全上下文是一个四元组字符串,格式如下:

user:role:type:level
# 级别(level)为可选,仅在使用 MLS(多级安全)或 MCS(多类别安全)时出现

典型示例:

unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
system_u:object_r:etc_t:s0
staff_u:staff_r:staff_t:s0:c1.c3

1.3 user / role / type 的语义

组件含义受谁影响
userSELinux 用户标识(非 Linux UID),用于关联同一用户身份的一组权限登录时的 PAM 映射、semanage user
role角色,定义 user 可以切换到的 type 集合,通常用于 RBAC(基于角色的访问控制)策略中 role allow 语句
type核心标识符,决定访问规则。进程的 type 称为域(domain),文件/资源的 type 用于判断是否允许读、写、执行等操作TE(Type Enforcement)规则
level敏感度+分类,用于 MLS/MCS 场景,控制更细粒度的隔离策略中的 level 关系,容器/虚拟化隔离
常见误区:Linux 用户(如 root、alice)与 SELinux 用户(如 unconfined_u、user_u)没有直接对应关系。一个 Linux 用户可以映射到多个 SELinux 用户,但每个登录会话只有一个。

1.4 进程与文件的上下文关系

每个进程在创建时从父进程继承安全上下文(域),每次对文件的访问都会携带自身的安全标识。策略引擎收到请求后,根据源 type(进程域)、目标 type(文件 type)以及操作类(read、write、execute 等)查找规则。若未匹配到 allow 规则,则拒绝并记录 AVC。

查看常用命令:

# 查看当前 SELinux 模式
getenforce

# 查看文件安全上下文
ls -Z /etc/passwd
# 输出示例: system_u:object_r:etc_t:s0  /etc/passwd

# 查看进程安全上下文
ps -Z $(pgrep sshd)
# 输出示例: system_u:system_r:sshd_t:s0-s0:c0.c1023

# 临时更改模式(重启后失效)
setenforce 0    # 切换到 Permissive
setenforce 1    # 切换到 Enforcing

持久化配置位于 /etc/selinux/config:

# 修改后需重启生效
SELINUX=enforcing       # enforcing | permissive | disabled
SELINUXTYPE=targeted    # targeted | mls | minimum

1.5 核心流程:上下文决策与验证

安全决策流程:
  1. 进程发出系统调用(如 open / read / write)。
  2. 内核 LSM 钩子捕获操作,收集进程安全上下文(sid)和目标文件的安全上下文(sid)。
  3. AVC(Access Vector Cache)查找匹配的 allow / dontaudit / auditallow 规则。
  4. 若未命中缓存,则查找二进制策略中的 TE 规则。
  5. 最终返回允许、拒绝(并记录审计日志)、或自动补全(conditional rules)。
调试定位:当应用被拒绝访问时,先查看 ausearch -m avc -ts recent 或 journalctl -t setroubleshoot。常见的拒绝原因包括:进程域与文件 type 不匹配、缺少 transition 规则、文件上下文被误改(如 /var/www 目录被标记为 user_home_t)。

1.6 本章知识结构总览

下图从宏观角度展示 SELinux 基本组件、进程/文件上下文、策略决策与日志输出的关系:

SELinux基础架构与安全上下文结构图 SELinux 基础架构与安全上下文关系 源:进程域(subject) unconfined_t user_u:user_r:user_t 客体:文件(object) etc_t system_u:object_r:etc_t 策略引擎(AVC + TE) 查找 allow / dontaudit 规则 匹配源 type → 目标 type 审计日志(AVC) ausearch / audit.log 决策结果 允许 / 拒绝 请求访问(open/read/write) 提供上下文 拒绝时记录 判定结论 角色与层次(role/level)影响域选择和约束 文件上下文由策略的 file_contexts 定义

1.7 常见错误与调试要点

错误现象根本原因排查命令 / 方法
服务启动失败,日志显示 Permission denied进程域缺少对文件 type 的 allow 规则ausearch -m avc -p <PID> | audit2allow
文件上下文被误标,如 home 目录文件显示 httpd_t文件创建时的上下文继承或 restorecon 错误restorecon -Rv /path
getenforce 显示 Disabled,但重启后又变回 Enforcing/etc/selinux/config 中 SELINUX=disabled 未设置编辑配置文件并重启
容器内部无法访问挂载卷宿主机文件 type 与容器域不匹配使用 semanage fcontext -a -t container_file_t 修改
性能注意:在大量文件操作的场景(如编译、大数据处理),尽量使用 dontaudit 规则抑制无关拒绝日志,避免 AVC 缓存击穿导致的系统负载上升。可通 semodule -DB 重建策略时关闭 dontaudit(调试用),生产环境用 semodule -B 保持默认。

1.8 本章小结