SELinux AVC denied 大量日志的 setroubleshoot / audit2allow 生成规则

3次阅读

audit2allow规则不生效的根本原因是SElinux策略加载顺序与进程实际安全上下文不一致,且audit2allow未自动归一化混杂的日志上下文。

SELinux AVC denied 大量日志的 setroubleshoot / audit2allow 生成规则

为什么 audit2allow 生成的规则经常不生效

根本原因不是规则写错了,而是 SELinux 策略加载顺序和类型上下文没对齐。比如你用 audit2allow -a/var/log/audit/audit.log 提取规则,但实际服务运行时用的是 system_u:system_r:httpd_t:s0 上下文,而日志里可能混着 unconfined_service_t 或旧容器残留的上下文——audit2allow 不会自动过滤或归一化这些。

实操建议:

  • 先确认出问题进程的真实上下文:ps -eZ | grep httpd(别只信日志里的 avc: denied 段落)
  • ausearch -m avc -ts recent | audit2why 看每条拒绝是否真该放行,避免把调试行为误当生产需求
  • audit2allow -a -M mypolicy 生成模块后,必须用 semodule -i mypolicy.pp 加载,semodule -l | grep mypolicy 验证是否在列表里
  • 如果用了容器(如 podman),默认走 container_t 域,audit2allow 生成的规则得手动加 typecontainer_runtime_t 或改用 podman run --security-opt label=disable 临时绕过排查

setroubleshootd 为啥没弹提示、日志也不更新

setroubleshootd 不是总在后台跑,它依赖 dbusabrt 服务联动,且只处理 avc 类型日志中「有对应策略模板」的拒绝事件。很多自定义服务或新内核模块触发的拒绝,它直接跳过——不是挂了,是压根没匹配上规则库。

实操建议:

  • 检查服务状态:systemctl status setroubleshootd,常见失败原因是 abrt-daemon 没启,得一起开:systemctl enable --now abrt-daemon setroubleshootd
  • 手动触发一次分析:sealert -a /var/log/audit/audit.log,比等弹窗快得多,输出里带具体建议命令
  • 如果 sealertNo such file or Directory: /var/lib/setroubleshoot/plugins,说明插件包没装全,补:dnf install setroubleshoot-plugins(RHEL/centos)或 apt install selinux-basicsdebian
  • 注意日志路径:默认只扫 /var/log/audit/audit.log,如果你用 rsyslog 转发到别的位置,setroubleshootd 不会自动发现

audit2allow -R(推荐规则)生成一无关 type_transition

audit2allow -R 试图基于策略语义推导“合理”规则,但它会把所有相邻的 avc 拒绝打包成一个宽松策略,比如把 httpd_t 访问数据库 socket 的拒绝,和 mysqld_t 创建文件的拒绝混在一起,生成一条 allow httpd_t mysqld_t : sock_file { write create }——这等于开了个口子,让 Web 进程能直接操作 MySQL 文件系统。

实操建议:

  • 禁用自动推荐:audit2allow -a -M myfix,然后人工看 myfix.te 里每条 allow 是否精准对应你观察到的行为
  • 重点删掉含 type_transitiondyntransentrypoint 的行,这类规则影响面大,90% 场景不需要
  • 如果只是要读配置文件,优先用 semanage fcontext -a -t httpd_config_t "/path/to/conf(/.*)?" + restorecon -Rv /path/to/conf,比硬塞 allow 更安全
  • 验证规则最小性:semodule -DB 关闭 debug 日志,再复现问题,看是否还有新 avc 日志——有就说明漏了,没有才代表够用

SELinux 重启后规则消失?模块加载失败的典型错误

最常踩的坑是把 .pp 文件放在错目录,或没处理模块依赖。SELinux 模块不是“加载即永久”,它依赖 semodule_store 路径和当前策略布尔值状态。比如你加载了允许 Samba 访问 NFS 的模块,但 samba_export_all_ro 布尔值是 off,那模块里的规则照样被策略引擎忽略。

实操建议:

  • 模块必须存在 /usr/share/selinux/packages//etc/selinux/targeted/modules/active/modules/ 才能持久;semodule -i 默认只存内存,重启丢
  • 查加载失败原因:semodule -n -i mypolicy.pp 2>&1 | grep -E "(fail|Error)",常见报错如 Failed to resolve allow rule 是因为引用了不存在的类型名
  • 依赖检查:seinfo -x mypolicy.pp 看是否引入了 sysnet_dns_port_t 这类需额外策略包支持的类型,缺的话得先装 selinux-policy-devel
  • 布尔值同步:getsebool -a | grep samba,确认相关布尔值已设为 on,否则模块规则形同虚设

真正麻烦的从来不是生成规则,而是搞清拒绝发生的上下文链:进程域 → 目标文件/端口类型 → 策略模块加载状态 → 布尔值开关。少盯一眼,就多调半小时。

text=ZqhQzanResources