SELinux 的两种模式(Enforcing 和 Permissive)有何区别?

解读

国内 Android 面试中,SELinux 属于“安全加固”高频考点。面试官通常想确认三件事:

  1. 你是否真的在 ROM 定制或车载/金融级项目中处理过强制访问控制(MAC)问题;
  2. 能否快速定位“avc denied”导致的功能失效;
  3. 是否理解国内合规(如工信部入网、央行终端检测)对 SELinux 状态的要求。
    回答时切忌只背定义,要结合“怎么查、怎么改、怎么验证”落地步骤,体现工程经验。

知识点

  1. 模式本质
    Enforcing:内核强制拒绝所有违反策略的访问,并在 kernel log 中记录 avc denied。
    Permissive:仅记录违反项,不真正拦截,用于调试策略。

  2. 状态读取与实时切换(需 root)
    getenforce 返回 Enforcing 或 Permissive;
    setenforce 0 切到 Permissive,setenforce 1 切回 Enforcing;
    重启后状态由 /etc/selinux/config 或 Android 的 BOARD_KERNEL_CMDLINE 中的 androidboot.selinux= 决定。

  3. 持久化配置差异
    国内 AOSP 源码编译:device/xxx/xxx/BoardConfig.mk 里设 BOARD_KERNEL_CMDLINE += androidboot.selinux=enforcing;
    出厂即要求 Enforcing,否则无法通过 Google GTS、国内 CTA、银联终端安全测试。

  4. 审计与策略修复流程
    抓取 avc denied:adb shell dmesg | grep avc,或 logcat -b all | grep denied;
    使用 audit2allow 生成临时 .te 补丁,合并到 device/xxx/sepolicy/,重新编译 sepolicy 并刷机;
    验证:重新压测功能 + getenforce 确认仍为 Enforcing + 不再出现新 denied。

  5. 国内特殊场景
    车载 IVI 系统常把第三方 APK 放在 vendor/app,需额外给 vendor_app 域开放 ioctl、binder_call 权限;
    金融 POS 终端要求 TEE 与 SELinux 双重强制,Permissive 模式直接判为高风险,无法过检。

答案

Enforcing 模式下,SELinux 策略被严格强制执行,任何违反策略的访问都会被内核拒绝,并在 log 中留下 “avc denied” 记录;Permissive 模式只记录不拦截,用于调试策略。
国内 Android 设备出厂必须保持 Enforcing,否则无法通过 CTA、GTS 及金融终端安全认证。
调试时可用 setenforce 0 临时切到 Permissive,抓完 denied 后用 audit2allow 生成补丁,合并到 sepolicy 源码并重新编译,刷机后确认 getenforce 仍为 Enforcing 且功能正常,即完成加固闭环。

拓展思考

  1. 如何在不 root 的前提下验证某款国内手机是否真为 Enforcing?
    答:adb shell getprop | grep selinux 看 ro.boot.selinux 与 ro.build.selinux.enforce 两个只读属性,若均为 enforcing 且 getenforce 返回 Enforcing,则无法被第三方应用篡改。

  2. Android 14 引入 SELinux Sandbox for Apps(用户空间策略重载),与系统级 Enforcing/Permissive 有何关系?
    答:系统仍为全局 Enforcing,但可为单个应用加载 mini-policy,实现“系统严格、应用宽松”的混合模型,对国内小程序容器、快应用引擎等场景有借鉴意义。