Linux内核分析之安全模块-02

54.1 AppArmor 配置文件模型

AppArmor 的策略单元是 profile:绑定到可执行路径(或通过 change_profile 显式进入),内部是一组"路径 glob + 权限字母"的允许规则,外加能力清单与网络/信号约束。两种模式(enforce/complain)决定违规的后果。本节解剖 profile 的语法与生命周期。


54.1.1 profile 语法:路径 glob + 权限字母

一个真实风格的 profile (/etc/apparmor.d/usr.sbin.nginx):

 /usr/sbin/nginx flags=(attach_disconnected) {
   #include <abstractions/base>          ← 通用规则集复用
   #include <abstractions/nameservice>

   capability net_bind_service,          ← 能力白名单 (55 章)
   capability setuid,
   network inet stream,                  ← 网络语义约束
   network inet dgram,

   /etc/nginx/**            r,           ← 路径 glob + 权限字母
   /var/log/nginx/*         rw,
   /var/lib/nginx/**        rwk,         ← k = 文件锁 (33.5 节)
   /usr/sbin/nginx          mr,          ← m=映射执行
   /{,usr/}lib{,32,64}/**   mr,
   /proc/*/environ          r,
   deny /etc/shadow         rwkl,        ← 显式拒绝 (优先审计)
   audit /etc/passwd        r,           ← 放行但记审计
 }

 权限字母表:
  r 读  w 写  a 追加  k 锁  l 链接  m 映射执行
  x 执行 (变体: ix=本profile内执行 / px=独立profile
        / ux=无约束执行 / cx=<子profile>)

 路径 glob:
  *   单级任意    **  多级任意    ?  单字符
  {}  括号选择    []  字符类

54.1.2 模式、附件与生命周期

两种模式 (aa_profile 的 mode 字段, policy.h:258 区):

 enforce  违规 = 拒绝 + 审计 (真正的 MAC)
 complain 违规 = 只审计不拒 (策略学习期:
   aa-genprof 工具"跑应用→收集日志→生成规则")

 profile 的三种绑定:
 [1] 路径附着: profile 名 = 可执行路径
     (exec 该文件 → 自动进入, 与 53.3.2 节
      SELinux 域迁移对照: 前提是"路径匹配"而非
      "四条策略规则")
 [2] 名称附着 (name=): 需显式 change_profile
     (PAM/容器运行时用)
 [3] hat / 子 profile: ^child 语法 — 主 profile
     内 exec 切入的子域 (邮件过滤管道模式)

 生命周期:
 apparmorfs 加载 profile (54.2 节) → 缓存哈希
 exec 触发 aa_replace_current_profile (domain.c:1226
   区) → 任务 ctx 指向新 profile (cred blob)
 卸载: 引用计数归零后释放 (RCU)

与 SELinux 的模型对照(本卷核心对照):

维度 SELinux AppArmor
标识 类型(语义标签) 可执行路径
策略库 全系统统一库 每应用独立 profile
新应用成本 需策略建模(域+类型+迁移) 无 profile=不受限;写 profile 增量
匹配对象 类型对类型 路径 glob
默认 全拒 无 profile 不受限
学习曲线 陡(全局建模) 平(按应用增量)

小结

AppArmor 的 profile 以"路径 glob + 权限字母 + 能力清单"表达最小权限,attach 到可执行路径实现自动进入,enforce/complain 两模式支撑从学习到强制的渐进部署;与 SELinux 的本质分野是"路径名 vs 类型"与"增量 vs 全局"——前者易部署、后者体系严密,两者都在 52 章框架下共存(堆叠)。下一节看内核如何执行这套 profile。

54.2 AppArmor 内核实现

AppArmor 的内核实现三件套:每任务的 aa_task_ctx(当前 profile 引用)、profile 内的 DFA 匹配器(路径 glob 编译成确定性自动机)、以及 apparmorfs 控制接口。本节解剖判定路径、DFA 与卸载语义。


54.2.1 任务上下文与判定路径

// security/apparmor/include/task.h:13
static inline struct aa_task_ctx *task_ctx(struct task_struct *task)
/* ctx: current_profile + previous (onexec/回退栈) */
// security/apparmor/domain.c:921/1226/1398(域切换三处调用点)
    struct aa_task_ctx *ctx;
判定的完整路径 (open 示例):

 apparmor_file_open (52.1 节 security_file_open 的消费端)
   ├─ task_ctx(current) → current_profile
   │   (NULL → 无 profile, 直接放行 — 54.1.2 节)
   ├─ 取路径: 该文件的绝对路径 (namespace 内相对)
   │   (54.1.1 节 attach_disconnected 处理匿名挂载)
   ├─ DFA 匹配 (match.c): 路径串过自动机
   │   → 命中规则的权限位掩码
   ├─ 与请求权限 (MAY_READ 等) 求交
   └─ 缺权限 → enforce: -EACCES + audit
                complain: 只 audit

 域切换 (aa_replace_current_profile, domain.c:1226 区):
   exec 时按 54.1.2 节绑定匹配 → ctx 换 profile
   (cred blob 的 AppArmor 柜位更新, 52.3.3 节)
   change_profile: 显式切换 (容器运行时进入容器
   profile 的通道)

54.2.2 DFA 匹配器与卸载

DFA (确定性有限自动机) 匹配器:

 加载期: 用户态把 profile 的全部路径 glob 编译
   成 DFA 转移表 (match.c 的 table 格式)
 运行期: 路径字符串逐字符过自动机
   → 终态 = 命中规则的权限位集
 优点: glob 语义一次编译, 运行期 O(路径长度)
   无回溯 — 比"逐条 glob 匹配"快且抗退化
 (SELinux 的对应物是 avtab 查询 — 53.2 节;
  两者都把"策略"预编译成高速结构)

 卸载/替换 (policy.c):
   profile 哈希表 RCU 替换 (53.2 节同款)
   旧 profile 引用计数 → 归零释放
   仍引用旧 profile 的任务: 继续按旧跑 (引用
   保护) 或按策略标记迁移
控制接口 (apparmorfs, /sys/kernel/security/apparmor):

 .access / profiles      profile 枚举与原始数据
 /proc/<pid>/attr/current  查/改任务当前 profile
                         (与 SELinux 的 attr 接口同形!)
 aa-status               全局统计 (enforce/complain 计数)
 加载: 用户态 apparmor_parser 编译 → 写入
   .load (policy.bin — 与 53.2.2 节 SELinux 装载
   接口同思想: 内核收二进制, 不解析源语法)

小结

AppArmor 内核实现的三件套:aa_task_ctx 持当前 profile 引用(无 profile 即放行)、glob 语义预编译为 DFA 自动机(O(路径长) 判定、无回溯)、apparmorfs 以二进制装载与 attr 接口对齐 SELinux 的管理形态;域切换落在 exec 钩子与 change_profile,卸载走 RCU 替换与引用回收。它与 SELinux 共享 52 章框架,而以"路径、增量、易用"作为工程取舍。安全对比的完整图景在 52-54 章间闭合。下一章回到 DAC 的精细化——Capability 与 cred。