Linux AppArmor 的 aa-genprof / aa-logprof 交互式 profile 生成流程

1次阅读

aa-logprof卡在提示是因为日志无足够denied事件或未读取正确日志源;需检查dmesg/journalctl中的apparmor拒绝记录,必要时手动指定日志路径输入。

Linux AppArmor 的 aa-genprof / aa-logprof 交互式 profile 生成流程

aa-logprof 为什么卡在“Please enter ‘1’, ‘2’ or ‘?’”却没显示规则选项

这是最常见的阻塞点:日志里没捕获到足够多的访问事件,或者 aa-logprof 没读到正确的日志源。它默认只看 /var/log/audit/audit.log(需 auditd 运行)或 /var/log/syslog(需 AppArmor 日志已启用),但很多系统默认只往 journald 写。

  • 先确认 AppArmor 实际记录了拒绝事件:sudo dmesg | grep -i apparmorsudo journalctl --no-pager -t kernel | grep -i "apparmor.*DENIED"
  • 如果 journalctl 有 DENIED 日志但 aa-logprof 看不见,手动指定日志路径:sudo aa-logprof -f /dev/stdin,然后把 journal 日志重定向进去:sudo journalctl --no-pager -t kernel | grep -i "apparmor.*DENIED" | sudo aa-logprof -f /dev/stdin
  • 确保目标程序已用 aa-enforceaa-complain 加载过 profile(哪怕空 profile),否则内核不会记录策略冲突

aa-genprof 启动后程序直接退出,profile 文件为空

aa-genprof 本质是启动一个带 trace 的子进程,靠 ptrace 捕获系统调用。如果被测程序是 setuid、由 systemd 管理、或本身做了反调试(比如某些 Go 二进制),它就无法注入和跟踪。

  • 不要用 sudo aa-genprof /usr/bin/myapp 直接跑特权程序;改用普通用户身份启动,并确保 profile 路径写对:sudo aa-genprof -d /etc/apparmor.d/usr.bin.myapp /usr/bin/myapp
  • systemd 服务?先停掉服务:sudo systemctl stop myapp.service,再用 aa-genprof 手动拉起二进制(不走 systemd)
  • Go 程序常见问题:加 GODEBUG=asyncpreemptoff=1 环境变量降低调度干扰,或换用 aa-logprof 配合真实运行日志更可靠
  • 检查 /proc/sys/kernel/yama/ptrace_scope,值为 12 会阻止非子进程 trace,临时设为 0echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope

生成的 profile 里出现大量 abstractions 和 include,能不能删

能删,但不建议盲目删。AppArmor 的 abstraction(如 abstraction/baseabstraction/nameservice)是预定义的通用权限集,删了可能让程序运行时因缺失必要权限而失败,尤其是 DNS 查询、动态库加载、信号处理等隐式行为。

  • 删之前先测试:注释掉某条 include <abstraction></abstraction>,用 sudo apparmor_parser -r /etc/apparmor.d/usr.bin.myapp 重载,再运行程序观察是否报新的 DENIED
  • 真正冗余的是未被触发的路径规则——比如 profile 里有 /tmp/** rw, 但程序从不读写 /tmp,这种可删;但 /etc/ssl/certs/** r, 很可能被 OpenSSL 隐式调用,删了 https 请求就失败
  • aa-unconfined 查看当前进程实际使用的 profile 和未匹配的访问:sudo aa-unconfined -v

profile 生效后程序报 “Permission denied” 但日志没新 DENIED 记录

说明不是 AppArmor 拒绝的,而是其他机制拦截了——最常见的是 SElinux(即使你只配了 AppArmor)、文件能力(file capabilities)、或 systemd 的 RestrictAddressFamilies= 等 sandbox 参数。

  • 先确认 AppArmor 确实在管这个进程:cat /proc/PID/attr/current(PID 是你的程序进程号),输出应含 myapp (enforce)myapp (complain);如果是 unconfined,说明 profile 没加载或匹配失败
  • 检查 profile 名称是否和二进制路径完全一致(包括符号链接):aa-status | grep myapp,若没出现,用 sudo aa-enforce /etc/apparmor.d/usr.bin.myapp 强制加载
  • systemd 服务要额外注意:ProtectSystem=NoNewPrivileges=PrivateTmp= 这些会覆盖 AppArmor 权限,得同步调整

AppArmor 的交互式工具依赖真实运行时行为,而不是静态分析。这意味着 profile 覆盖度完全取决于你“怎么用”那个程序——漏掉某个菜单、某个配置文件、某次网络请求,对应权限就会缺。别指望一次跑完就收工。

text=ZqhQzanResources