2. 策略语言入门:te 文件语法、规则类型、allow 与 auditallow

2.1 te 文件语法基础

SELinux 策略的核心载体是类型强制(Type Enforcement,TE)文件,后缀为 .te。一个标准的 te 文件遵循固定的结构,由模块声明、类型/属性声明、规则列表三部分组成。所有策略语句都必须以分号结尾,注释使用 #。

  • 模块声明:policy_module(模块名, 版本号),每个独立策略包必须以此为开头。
  • 类型/属性声明:type 类型名; / attribute 属性名;,定义主体与客体的安全标签。
  • 规则列表:由 allow、auditallow、dontaudit、neverallow 等规则构成,描述访问控制矩阵。
最小 te 文件骨架:
policy_module(myapp, 1.0.0)

type myapp_t;
type myapp_data_t;
type myapp_exec_t;

allow myapp_t myapp_data_t:file read;
allow myapp_t myapp_exec_t:file execute;

2.2 规则类型总览

SELinux 提供四种核心规则类型,分别对应不同的授权与审计策略。下表从授权效果、审计行为和编译期检查三个维度进行对比:

规则类型 授权效果 审计行为 编译期检查 典型用途
allow 授予访问权限 不记录(默认静默) 无 日常正常访问路径
auditallow 授予访问权限 强制记录成功访问 无 合规审计、敏感操作
dontaudit 拒绝访问(不授权) 不记录(静默拒绝) 无 压制预期内的拒绝噪声
neverallow 编译期禁止规则存在 不适用 强制校验 安全基线、全局约束
关键区分:allow 只授权不审计;auditallow 授权且强制审计;dontaudit 拒绝且不记录;neverallow 在编译时禁止某类规则出现,是静态约束,不产生运行时效果。

2.3 策略语言体系结构

下图完整展示了 te 文件到规则类型的层次关系,以及 allow 与 auditallow 在策略体系中的位置:

SELinux 策略语言体系结构图 te 文件结构 policy_module + 类型声明 + 规则列表 规则类型分类 allow │ auditallow │ dontaudit │ neverallow allow 规则 授予主体对客体的访问权限 格式: allow S T:C P; auditallow 规则 授权 + 强制记录审计日志 格式: auditallow S T:C P; 其他规则类型 dontaudit:静默拒绝 neverallow:编译期检查 策略编写核心要点 主体(Source) → 客体(Target) : 类别(Class) { 权限集(Permissions) } 每一条规则都必须明确这四个要素,缺一不可

2.4 allow 规则详解

allow 是策略中使用最频繁的规则类型,格式为:

allow source_type target_type:class perm_set;
  • source_type:主体类型(通常是进程域)。
  • target_type:客体类型(文件、套接字、进程等)。
  • class:客体类别(file、dir、tcp_socket、unix_stream_socket 等)。
  • perm_set:权限集合,可以是单个权限或花括号包裹的权限列表。
实际示例:
# 允许 myapp_t 读取 myapp_data_t 类型的文件
allow myapp_t myapp_data_t:file read;

# 允许 myapp_t 创建并连接 TCP 套接字
allow myapp_t self:tcp_socket { create bind connect listen accept };

# 允许 myapp_t 对 data 目录执行搜索与遍历
allow myapp_t myapp_data_t:dir { search read getattr };

权限集合支持使用通配符 *(表示该类下的所有权限)和 ~(表示排除指定权限后的所有权限)。但生产环境应遵循最小权限原则,避免过度授权。

性能提醒:过度使用通配符会扩大攻击面,同时增加策略缓存压力。建议始终显式列出所需的最小权限集。

2.5 auditallow 规则详解

auditallow 的语法与 allow 完全一致,区别在于:每当规则匹配成功时,内核会强制向 /var/log/audit/audit.log 写入一条 AVC 审计记录。格式:

auditallow source_type target_type:class perm_set;

典型应用场景:

  • 合规审计:记录所有对敏感配置文件的写操作。
  • 安全监控:记录域转换、特权提升等高危操作。
  • 策略调试:临时开启 auditallow 验证规则是否命中。
审计日志示例:
# 对日志文件启用 auditallow
auditallow myapp_t myapp_log_t:file { write append };

# 触发写入时,audit.log 中会出现:
type=AVC msg=audit(1712345678.123:456): \
  avc:  granted  { write } for  pid=1234 \
  comm="myapp" path="/var/log/myapp/app.log" \
  scontext=system_u:system_r:myapp_t:s0 \
  tcontext=system_u:object_r:myapp_log_t:s0 \
  tclass=file
最佳实践:auditallow 会产生大量日志,高流量路径上请谨慎使用。建议先通过 audit2allow 从日志中提取必要规则,再决定哪些操作需要永久审计。

2.6 规则调试与验证

当策略行为不符合预期时,通过以下流程快速定位:

  1. 查看审计日志:ausearch -m avc -ts recent 或 grep AVC /var/log/audit/audit.log
  2. 使用 audit2allow 生成候选规则:
# 从日志中提取缺失的 allow 规则
grep "denied" /var/log/audit/audit.log | audit2allow -M mylocal

# 直接查看建议的 te 规则文本
grep "denied" /var/log/audit/audit.log | audit2allow
  1. 应用规则并重载策略:semodule -i mylocal.pp
  2. 确认规则生效:sesearch --allow -s myapp_t -t myapp_data_t -c file
快速验证单条规则是否生效:
# 使用 sesearch 检查策略中是否存在指定规则
sesearch --allow -s myapp_t -t myapp_data_t -c file -p read

# 输出示例:
Found 1 semantic av rule:
   allow myapp_t myapp_data_t : file { read };

2.7 常见错误与避坑

错误类型 典型表现 解决方案
类型未声明 编译报错:unrecognized type 在规则前添加 type 类型名; 声明
类别/权限拼写错误 编译报错:unknown class 或 unknown permission 查阅 selinux-class-permissions 支持列表
通配符权限过于宽泛 安全审计失败,或策略无法加载 替换 * 为显式权限列表,遵循最小权限
auditallow 日志洪泛 磁盘空间被审计日志迅速填满 移除高频路径的 auditallow,改用 allow
规则顺序依赖 先 deny 后 allow 导致意外拒绝 策略编译器按文件顺序合并,尽量将通用规则前置
避坑口诀:先声明后引用,类别权限要对照,通配慎用显式好,审计开关看场景,编译错误查拼写,运行问题看日志。

掌握 te 文件语法和规则类型是编写 SELinux 策略的基石。下一层将深入类型声明与属性机制,理解如何利用属性简化大规模策略的维护。