第4章 常见拒绝根因定位方法:策略缺失、布尔值关闭、文件/进程上下文错误、dontaudit规则屏蔽、多域交互冲突;故障树分析法

现象识别

avc: denied 日志是 SELinux 拒绝的唯一直接证据。典型特征:日志中包含 type=AVC msg=audit(...),并附带 scontext(源上下文)、tcontext(目标上下文)、tclass(资源类别)、permission(被拒绝的操作)。拒绝动作本身可能表现为进程报错、文件无法访问、端口绑定失败等,但根因隐藏在 AVC 日志中。

日志示例

type=AVC msg=audit(1680000000.123:456): avc:  denied  { read } for  pid=1234 comm="httpd" name="config" dev="dm-0" ino=5678 scontext=system_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:default_t:s0 tclass=file

解读:httpd_t 试图读取一个标记为 default_t 的文件,策略未允许 httpd_t 对 default_t 文件的 read 权限。

数据采集

  1. 收集最新的 AVC 日志:ausearch -m avc --start recent 或 cat /var/log/audit/audit.log | grep denied。
  2. 确认当前布尔值状态:getsebool -a | grep -E 'httpd|ftpd|named'(根据涉及进程筛选)。
  3. 检查文件上下文:ls -Z /path/to/problem/file 或 matchpathcon /path。
  4. 检查进程上下文:ps -Z -p PID。
  5. 确认是否被 dontaudit 规则静默:semodule -l | grep dontaudit(临时关闭 dontaudit 可暴露静默拒绝:semodule -DB)。

原因定位——故障树分析法

下图展示从 AVC 拒绝日志到五种常见根因的决策分支。故障树顶部是“avc denied 日志”,向下按“权限是否明确允许?”、“上下文是否匹配?”、“布尔值是否开启?”、“是否存在 dontaudit 规则?”、“多域交互是否冲突?”层层分解。

SELinux 拒绝根因故障树 avc denied 日志 策略中已有允许规则? 否 是 策略缺失 上下文/布尔值/规则问题 布尔值关闭? 文件/进程上下文错误 dontaudit 规则屏蔽 多域交互冲突 域间过渡/访问限制 故障树使用步骤 ① 从“avc denied 日志”开始,检查策略中是否存在允许该操作的规则。 ② 若有规则仍拒绝,沿右分支检查:布尔值是否关闭?上下文是否匹配? ③ 若上下文正确,检查是否被 dontaudit 静默屏蔽,或存在多域交互冲突。 ④ 每个叶子节点对应一种根因,参考下表进行修复。 ⑤ 修复后复测,若仍有拒绝则返回上层节点重新排查分支。

根因排查对照表

根因判断规则典型日志特征修复动作
策略缺失 使用 audit2allow -a 生成策略模块,若出现新权限则说明缺失。 日志中 scontext=t:类型A 对 tcontext=t:类型B 请求某权限。
ausearch -m avc --start recent | audit2allow -M mypolicy
semodule -i mypolicy.pp
布尔值关闭 检查涉及进程的布尔值:getsebool httpd_can_network_connect。
若为 off 则关闭。
日志中 comm="httpd" 但 permission 为 name_connect 等受布尔值控制的权限。
setsebool -P httpd_can_network_connect on
文件/进程上下文错误 ls -Z target_file 确认是否为预期类型。
ps -Z -p PID 确认进程域是否正确。
日志中 tcontext=...:unlabeled_t 或 tcontext=...:default_t。
semanage fcontext -a -t httpd_sys_content_t '/var/www(/.*)?'
restorecon -Rv /var/www
dontaudit 规则屏蔽 执行 semodule -DB 后重新触发操作,若出现新 AVC 日志则说明之前被屏蔽。 原始日志不存在,但 ausearch 无结果,而操作实际失败。
semodule -DB   # 重建 dontaudit 规则(开发用)
# 修复后恢复:semodule -B
多域交互冲突 检查域间过渡规则:sesearch -s domA -t domB -c process -p transition。
若缺少过渡权限或类型强制规则。
日志中 permission=transition 或 entrypoint,且涉及两种不同域。 编写策略模块允许域间过渡,或使用 type_transition 规则。

修复动作

  • 策略缺失:使用 audit2allow 生成本地策略模块并加载。
  • 布尔值关闭:setsebool -P <name> on 永久开启。
  • 上下文错误:semanage fcontext 修正文件类型标签,再执行 restorecon;对进程使用 runcon 或调整启动脚本的 Type= 域。
  • dontaudit 屏蔽:仅开发环境使用 semodule -DB 暴露拒绝,生产环境应编写 auditallow 规则并移除 dontaudit。
  • 多域交互冲突:添加 allow domA domB:process transition; 并设置 type_transition。

警告:semodule -DB 会重建整个策略,可能造成额外拒绝日志。使用前请备份当前策略:semodule -l > module_backup.txt。完成后务必执行 semodule -B 恢复默认 dontaudit 规则。

复测

  1. 重新触发被拒绝的操作(如重启服务、访问文件、尝试端口连接)。
  2. 检查最新审计日志:ausearch -m avc --start recent | tail -20。
  3. 确认无新增 denied 记录。若有,返回故障树重新定位。
  4. 对于 dontaudit 场景,复测前需先 semodule -B 恢复屏蔽规则,确保操作被允许且不再记录。

预防

  • 策略开发阶段:使用 audit2allow 自动化生成初始策略,避免手工遗漏。
  • 布尔值审计:定期执行 getsebool -a | grep 'off' 检查关键布尔值状态。
  • 文件上下文基线:使用 semanage fcontext -l 维护自定义文件类型列表,配合 restorecon -R 脚本确保一致性。
  • 禁止滥用 dontaudit:除开发者沙箱外,生产环境避免使用 semodule -DB,应编写显式 auditallow 规则代替。
  • 多域交互测试:在部署前利用 sesearch 和 apol(SETools)验证域间过渡路径是否完整。