Linux SELinux 高级策略调优

2次阅读

selinux策略修改后不生效是因为需先编译(checkmodule)再打包(semodule_package)并加载(semodule -i),且必须指定模块名(-n)、正确设置文件上下文并执行restorecon,否则规则无法触发。

Linux SELinux 高级策略调优

SELinux 策略为什么改了还不生效?

因为策略编译和加载是两步,且内核只认 policy.kern 这个二进制格式——直接改 te 文件或 if 文件不会触发任何变化。

  • 必须用 checkmodule -M -m -o policy.mod policy.te 编译模块源码
  • 再用 semodule_package -o policy.pp policy.mod 打包成可加载包
  • 最后用 semodule -i policy.pp 加载(注意:不是 load_policy,那是重启时用的)
  • 常见错误:semodule -iPermission denied?检查当前 shell 是否在 sysadm_runconfined_r 下,普通用户即使 sudo 也受限于角色域

如何让自定义策略不被 semodule -r 清掉?

默认 semodule 安装的是“命名模块”,卸载时按名匹配;但如果你用 -i 装了未命名包(比如没指定 -n myapp),它会被归为“无名模块”,semodule -l 看不见,semodule -r 也删不掉,只能靠 semodule -b /etc/selinux/targeted/modules/active/base.pp 强制回滚整个基础策略——非常危险。

  • 安装时务必加 -n myapp:例如 semodule -i -n myapp policy.pp
  • 升级策略时用 -u 替换而非 -i,否则同名模块会叠加而非覆盖
  • semodule -l | grep myapp 能查到才算真正注册成功
  • 模块名不能含下划线或点号,只支持小写字母、数字、短横线

audit2why 显示 allowed 但实际被拒绝?

说明 AVC 拒绝日志里混着多个原因,audit2why 只挑了一个路径解释,而真实拦截点可能在另一条策略链上,比如 file_contexts 不匹配导致类型标注失败,后续所有规则都失效。

  • 先跑 ausearch -m avc -ts recent | audit2why 看完整拒绝链
  • 重点检查 ls -Z 输出的目标文件上下文是否真为你期望的 type(比如你写了 allow httpd_t myapp_log_t:file { read write };,但日志文件其实是 var_log_t
  • semanage fcontext -a -t myapp_log_t "/var/log/myapp(/.*)?" 注册上下文,再执行 restorecon -Rv /var/log/myapp
  • 别跳过 restorecon:SELinux 不自动重标已存在文件,只对新建文件生效

为什么 setsebool -P 不持久?

因为 -P 只把布尔值写进 /etc/selinux/targeted/modules/active/Booleans.local,但某些发行版(如 RHEL 8+)默认启用 selinux-policy-devel 包,它会在每次策略更新时清空这个文件并重建 booleans 数据库

  • 确认布尔值是否真写入:semanage boolean -l | grep your_bool,看 defaultcurrent 列是否一致
  • 若不一致,手动运行 semanage boolean -m --on your_bool(这会走数据库接口,比 setsebool 更底层)
  • 检查 /etc/selinux/configSELINUXTYPE 是否与当前加载策略名完全一致(大小写敏感),否则 semanage 会静默失败
  • 容器环境里 setsebool 基本无效——宿主机策略不传递到容器进程域,得用 podman run --security-opt label=type:your_type

SELinux 策略调优最麻烦的从来不是写规则,而是搞清当前生效的是哪一版策略、哪个上下文、哪条布尔值——三个地方各改一半,问题反而更难复现。

text=ZqhQzanResources