4. IMA框架集成:内核IMA配置、IMA策略编写、IMA日志收集

好,咱们进入第四章。IMA(Integrity Measurement Architecture)这东西,说白了就是内核里的一把锁——它负责在文件被访问、被执行之前,先算个哈希,记个账。你想想看,如果固件启动后,谁改了关键文件都不知道,那前面做的所有信任链工作都白费了。

我个人习惯把IMA看作“运行时度量的大门”。它不负责度量谁,但它提供了一套机制:你写策略,它执行;你收日志,它记录。今天我们就从配置、策略、日志三个角度把它讲透。

核心要点:IMA 不是默认开启的,需要内核配置 + 启动参数 + 策略文件三者配合。缺一个,度量就出不来。

4.1 内核IMA配置

先看内核配置。我记得第一次搞IMA时,光找配置项就花了半天。其实没那么复杂,关键就几个开关。

配置项 说明 推荐值
CONFIG_IMA IMA 主开关,不选这个后面全白搭 y
CONFIG_IMA_MEASURE_PCR_IDX 度量值写入 TPM 的哪个 PCR 寄存器 10
CONFIG_IMA_AUDIT 是否开启审计日志,建议开 y
CONFIG_IMA_WRITE_POLICY 允许运行时写入策略,调试阶段很有用 y
CONFIG_IMA_READ_POLICY 允许读取当前策略,方便验证 y
CONFIG_IMA_APPRAISE IMA 评估模式,不仅度量还校验签名 按需

配置完这些,重新编译内核。嗯,这里要注意:如果你用的是发行版内核,可能已经带了IMA,但策略是空的。你可以先检查一下:

# 检查内核是否支持 IMA
cat /boot/config-$(uname -r) | grep CONFIG_IMA

# 如果输出是 CONFIG_IMA=y,说明内核已经支持
# 如果没输出,那就得自己编译内核了

小技巧:我建议在开发阶段把 CONFIG_IMA_WRITE_POLICY 和 CONFIG_IMA_READ_POLICY 都打开。这样你可以动态调整策略,不用每次改完都重启。等生产环境再关掉。

4.2 IMA策略编写

策略是IMA的灵魂。没有策略,IMA就是个空壳子,啥也不干。策略文件通常放在 /etc/ima/ 或者 /sys/kernel/security/ima/policy 里。

策略的语法其实不复杂,核心就是:谁(路径/文件类型)在什么条件下(执行/读取)做什么(度量/评估)。

4.2.1 策略语法基础

一条策略长这样:

# 格式:action func [mask] [fsmagic] [fsuuid] [uid] [gid] [fowner] [fgroup]
measure func=BPRM_CHECK
measure func=FILE_MMAP mask=MAY_EXEC
appraise func=FILE_CHECK mask=MAY_READ fowner=0

我来解释一下这几个关键字段:

  • action:measure(度量)、appraise(评估)、audit(审计)
  • func:触发点,比如 BPRM_CHECK(执行程序时)、FILE_MMAP(内存映射时)、FILE_CHECK(文件打开时)
  • mask:访问权限,MAY_EXEC、MAY_READ、MAY_WRITE
  • fowner:文件所有者,0 表示 root

避坑指南:我曾经在生产环境上犯过一个错——策略写得太宽,把所有文件都度量了。结果系统启动慢了3倍,日志文件几分钟就撑爆了。记住:策略要精准,只度量你关心的关键路径。

4.2.2 实战策略示例

下面是我在项目中常用的一个策略模板,你可以直接拿来改:

# 度量所有可执行文件
measure func=BPRM_CHECK

# 度量所有 root 拥有的关键配置文件
measure func=FILE_CHECK mask=MAY_READ fowner=0

# 度量 /etc 下的所有文件
measure func=FILE_CHECK mask=MAY_READ fsmagic=0x01021994

# 度量特定路径
measure func=FILE_CHECK mask=MAY_READ obj=/usr/bin/*

# 不度量临时目录(提高性能)
dont_measure func=FILE_CHECK mask=MAY_READ obj=/tmp/*
dont_measure func=FILE_CHECK mask=MAY_READ obj=/var/tmp/*

加载策略的方式有两种:

# 方式一:启动时通过内核参数加载
# 在 GRUB 中添加 ima_policy=tcb

# 方式二:运行时写入(需要 CONFIG_IMA_WRITE_POLICY)
echo "measure func=BPRM_CHECK" > /sys/kernel/security/ima/policy

个人经验:我建议先用方式二调试。写一条策略,看一条日志,确认没问题了再固化到启动参数里。这样出了问题好回滚。

4.3 IMA日志收集

策略写好了,度量也跑了,日志在哪看?IMA 的日志主要有两个去处:内核环形缓冲区和 安全文件系统。

4.3.1 查看实时日志

最直接的方式是看 dmesg:

# 查看 IMA 相关的内核日志
dmesg | grep -i ima

# 输出示例:
# [    5.123456] ima: No TPM chip found, activating TPM-bypass!
# [    5.123789] ima: Allocated hash algorithm: sha256
# [    5.124012] ima: No policy loaded, measuring everything

但 dmesg 只显示启动阶段的日志。运行时度量记录在 /sys/kernel/security/ima/ 下:

# 查看度量列表
cat /sys/kernel/security/ima/ascii_runtime_measurements

# 输出格式:
# PCR 模板哈希 文件名 文件哈希 签名
# 10 sha256:xxx /usr/bin/bash sha256:yyy none

4.3.2 日志格式解析

每一条度量记录包含以下字段:

字段 说明 示例
PCR 写入的 PCR 索引 10
模板哈希 度量模板的哈希值 sha256:abc123...
文件名 被度量文件的路径 /usr/bin/bash
文件哈希 文件内容的哈希值 sha256:def456...
签名 文件的数字签名(如果有) none / 签名值

4.3.3 日志持久化

默认情况下,IMA 日志只存在内存里,重启就丢了。如果你需要持久化,我建议用 auditd 配合:

# 安装 auditd
apt-get install auditd

# 配置 auditd 捕获 IMA 事件
echo "-w /sys/kernel/security/ima/ascii_runtime_measurements -p r -k ima_log" >> /etc/audit/rules.d/ima.rules

# 重启 auditd
systemctl restart auditd

# 查看 IMA 审计日志
ausearch -k ima_log

注意:日志量可能会很大。我曾经在一个高负载服务器上,每秒产生上千条度量记录。建议设置日志轮转,或者只度量关键路径。

4.4 IMA 框架整体流程

为了让你更直观地理解 IMA 的工作流程,我画了一张图:

IMA 框架工作流程 文件访问/执行 IMA 策略匹配 计算文件哈希 写入度量日志 扩展 TPM PCR 说明: 1. 文件被访问时触发 IMA 策略检查 2. 匹配的策略决定是否度量、评估或审计 3. 度量结果同时写入日志和 TPM PCR(如果有 TPM)

4.5 常见问题与排查

最后,我总结几个我在项目中踩过的坑:

  • 日志为空:检查策略是否加载成功。cat /sys/kernel/security/ima/policy 看看有没有内容。
  • 度量不生效:确认内核参数 ima_policy= 是否正确。我曾经因为拼写错误,策略根本没加载。
  • TPM 报错:如果没有 TPM 芯片,IMA 会进入 bypass 模式,日志照常记录,但不会扩展 PCR。这不影响功能。
  • 性能问题:如果系统变慢,检查是不是度量了太多文件。用 dont_measure 排除临时目录和只读文件系统。

调试小技巧:我习惯在开发阶段把 ima_policy=tcb 和 ima_appraise=off 一起用。这样只度量不评估,既能看日志又不会因为签名校验失败导致程序跑不起来。