AppArmor 配置文件堆叠下的信号与Ptrace规则修复
概述
AppArmor 是一个重要的 Linux 内核安全模块,用于限制程序的资源访问。在容器化环境中,容器运行时(如 containerd)通常为容器进程加载特定的 AppArmor 配置文件以增强安全性。然而,在特定的内核配置(如启用配置文件堆叠)和操作(如通过 kubectl exec 进入容器)下,原有的安全规则可能无法正确匹配进程的身份(peer),导致合法操作被内核拒绝,产生安全审计事件,甚至影响进程的正常运行。本文档阐述了这一问题的成因、影响以及对应的修复方案,对维护容器环境的安全性与可靠性至关重要。
核心概念
- AppArmor 配置文件堆叠 (Profile Stacking):这是 AppArmor 的一项高级特性(由
/sys/kernel/security/apparmor/features/domain/stack控制)。它允许为一个进程同时应用多个安全配置文件,主配置文件(如cri-containerd.apparmor.d)与一个通过特殊语法(如//&unconfined)声明的附加配置文件进行堆叠。这提供了更灵活和细粒度的安全策略。 - CRI ExecSync:容器运行时接口(CRI)中的一种操作,对应
kubectl exec或基于 exec 的存活探针/就绪探针。它在运行中的容器内创建一个新进程。 - Peer 名称匹配:在 AppArmor 的
signal和ptrace规则中,可以使用peer=关键字指定允许交互的目标进程的配置文件名称。规则是否生效,取决于发起进程的配置文件与peer=指定的值是否匹配。 - 问题根源:当通过
exec创建的进程(如 Go 运行时发送SIGURG用于 goroutine 抢占)运行在堆叠配置文件 (cri-containerd.apparmor.d//&unconfined) 下时,原有的peer={{.Name}}(展开为cri-containerd.apparmor.d)规则无法匹配到cri-containerd.apparmor.d//&unconfined这个 peer,导致内核拒绝操作。
实践
本次修复通过在容器的 AppArmor 配置文件模板中增加通配符规则来解决匹配问题。
修复方案:
在容器的 AppArmor 配置文件模板(由 containerd 生成)的 signal 和 ptrace 规则中,将原有的 peer={{.Name}} 规则修改为包含通配符的版本,使其能同时匹配基础配置文件名和堆叠后的配置文件名。
修改后的规则示例:
signal (send) peer={{.Name}},
signal (send) peer={{.Name}}//&*,
ptrace (trace, read, traceby, readby) peer={{.Name}},
ptrace (trace, read, traceby, readby) peer={{.Name}}//&*,
其中 //&* 是一个通配符模式,能够匹配任何堆叠配置文件的后缀(例如 //&unconfined)。
应用步骤:
- 更新 containerd:部署包含了此修复的 containerd 版本(PR #12887 之后)。
- 加载配置文件:使用
apparmor_parser --replace <profile_file>命令将更新后的配置文件加载到内核中。此步骤确保新规则生效。 - 验证修复:在启用了 AppArmor 配置文件堆叠的内核(如测试中使用的 6.17)上,执行类似
kubectl exec <pod> -- cat /proc/self/attr/apparmor/current的命令,确认新进程运行在堆叠配置文件下。然后监控系统审计日志(如audit.log),确认在一段时间内(例如执行多次 exec 操作后)不再出现之前那样的apparmor="DENIED" operation="signal"事件。
测试环境参考:
- 操作系统:Ubuntu 25.10 (questing) aarch64
- 内核版本:6.17.0-1007-raspi
- AppArmor 解析器:5.0.0~alpha1
- containerd 版本:v2.1.5-k3s1
SRE 要点
- 与可靠性的关联:此修复直接消除了因安全规则误报导致的进程信号被拒绝的风险。信号(如
SIGURG)是进程间协作(如 Go 的 goroutine 调度)的关键机制。被拒绝可能导致进程挂起、性能下降甚至故障,修复后显著提升了容器内应用的运行可靠性。 - 与可观测性的关联:修复前,系统审计日志中会出现大量由 AppArmor 生成的
DENIED事件。这些“噪音”会干扰 SRE 对真实安全威胁或系统异常的监控和告警。修复后,审计日志变得更加干净,有助于提高可观测性数据的质量。 - 最佳实践与反模式:
- 最佳实践:在设计和测试 AppArmor 策略时,必须考虑包括配置文件堆叠在内的各种进程身份模式。使用通配符(如
//&*)来增强规则的健壮性,是应对动态进程环境的有效手段。 - 常见反模式:在安全策略中硬编码或假设固定的进程身份(如只使用
peer={{.Name}}),在复杂的容器和编排环境中容易失效。这属于一种脆弱的静态配置反模式。
- 最佳实践:在设计和测试 AppArmor 策略时,必须考虑包括配置文件堆叠在内的各种进程身份模式。使用通配符(如
- 相关指标:
- SLI:可以将“由于 AppArmor 拒绝导致的进程信号发送失败次数”作为一个可靠性 SLI。本修复旨在将该指标降至零。
- SLO:可以设定一个 SLO,例如“在 99% 的
exec操作中,不应因 AppArmor 策略问题导致基础进程通信失败”。
相关页面:apparmor, kubernetes-exec