apparmor profile 编译失败多因工具链缺失或内核未启用,需装apparmor-utils并确认/sys/kernel/security/apparmor/存在;加载后须重启服务且profile名须严格匹配二进制路径;complain/enforce模式切换用-c/-e参数,语法错误常见于引号不匹配和deny位置不当。

profile 编译失败:找不到 apparmor_parser 或提示 command not found
多数情况是 AppArmor 工具链没装全,不是 profile 写错了。Ubuntu/Debian 默认不装 apparmor-utils,只装了内核模块和基础库。
- 运行
which apparmor_parser确认是否存在;不存在就先装包:sudo apt install apparmor-utils(Debian/Ubuntu)或sudo dnf install apparmor-utils(Fedora) - 注意:
apparmor_parser不在apparmor主包里,也不在kernel-modules-extra里,漏装就直接没法用 - 某些最小化系统(如 Docker 容器、Cloud-init 启动的实例)压根没启用 AppArmor,
ls /sys/kernel/security/apparmor/返回空说明内核没加载模块,此时装工具也没用
profile 加载后没生效:aa-status 不显示进程,或进程仍处于 unconfined
加载成功 ≠ 自动绑定进程。AppArmor profile 是按程序路径匹配的,不是按进程名,也不是靠“启动时自动加载”。
- 确认 profile 文件里
abstraction或include引用的路径存在,比如/etc/apparmor.d/usr.sbin.nginx中写了include <abstractions></abstractions>,就得确保/etc/apparmor.d/abstractions/base存在且语法合法 - profile 名必须与二进制路径严格对应(支持通配符但需谨慎),例如想约束
/usr/local/bin/myapp,profile 文件名应为/etc/apparmor.d/usr.local.bin.myapp,否则apparmor_parser -r会静默忽略 - 加载后需重启目标服务才能触发匹配,
systemctl restart myapp.service比kill -9 && ./myapp可靠——后者可能绕过 systemd 的AppArmorProfile=设置
complain 模式 vs enforce 模式:切错模式导致服务崩溃或日志爆炸
两者行为差异极大,但命令只差一个参数,极易误操作。complain 模式只记录违规不阻止,enforce 才真正拦截。
- 切换模式用
-C(complain)或-E(enforce),不是改 profile 文件里的注释。执行sudo apparmor_parser -r -C /etc/apparmor.d/usr.bin.python3就把该 profile 切到 complain;去掉-C就是 enforce - complain 模式下,
dmesg | grep apparmor会刷屏输出拒绝日志,尤其对频繁 open/read 的程序(如数据库、日志轮转脚本),可能撑爆 ring buffer 或被 syslog 限流丢弃 - enforce 模式上线前务必在 complain 下跑够时间(至少覆盖完整业务周期),否则一开就
Permission denied,常见于漏写/proc/*/status、/sys/devices/**或动态生成的 socket 路径
profile 语法错误导致 apparmor_parser 静默失败或部分加载
AppArmor 解析器对语法错误容忍度低,但错误提示极简,常卡在“没反应”或只报行号不报原因。
- 最常见的是引号不匹配:路径含空格或特殊字符时,必须用双引号包裹,如
"/opt/my app/bin/**" mrw,;单引号或不加引号都会解析失败 -
deny规则必须放在allow后面,否则会被覆盖(规则顺序敏感),而 parser 不报错,只是 deny 不生效 - 使用
abstraction时,路径必须以开头、<code>>结尾,写成abstractions/base或<abstractions> 都会静默跳过整段包含内容</abstractions> - 调试建议:先用
sudo apparmor_parser -Q -v /path/to/profile(-Q表示只检查不加载),看是否输出Syntax OK










